2016-08-26 17 views
0

私は関数を作成して.sqlファイルに保存しました。このファイルと関数を使用してファイルをシステムに配置し、コマンドラインからその関数を実行すると、新しいデータがそのシステムのデータベースに保存されます。コマンドラインからpsql関数スクリプトを保存して実行しようとしています

現在、私の.sqlファイルの内容は次のとおりです。

CREATE OR REPLACE 
FUNCTION device_authorisation_change(device_identification VARCHAR) 
RETURNS VARCHAR AS 
$$ 
DECLARE 
    OWNER varchar(255); 
    DEVICE_ID integer; 
    OWNER_ID integer; 
    DATE_TIME timestamp; 

BEGIN 
    OWNER := 'MyDefaultOrganisation'; 
    DATE_TIME := current_timestamp; 

    DEVICE_ID := (SELECT id from device dev where dev.device_identification = $1); 
    OWNER_ID := (SELECT id from owners own where own.owner_identification = OWNER); 

    DELETE FROM device_authorization 
    WHERE device = DEVICE_ID AND owner = OWNER_ID; 

    INSERT INTO device_authorization(id, creation_time, device, owner) 
    VALUES (nextval('device_authorization_id_seq'), DATE_TIME, DEVICE_ID, OWNER_ID); 

    RAISE NOTICE 'Deleted device authorisations for % for device: %' , OWNER, $1; 

    RETURN ''; 
END; 
$$ LANGUAGE plpgsql; 

私はコマンドを使用してファイルを実行しようとすると、私は、次のコマンド

psql -d my_database -f ChangeOwnership.sql -v device_identification='TestDevice' 

を使用して結果があることを示しde device_identificationはNULLと思われます。しかし、関数は、データベースに格納されて取得し、私は

SELECT "device_authorisation_change"('TestDevice'); 

この時間を使用して(pgAdminでで)この機能を実行することができ、機能が十分に実行されます。

私が達成したいのは、(名前付き)引数を使用してコマンドラインからsqlスクリプトを実行できることです。これはデータベースのデータをただちに更新します。データベースに関数を保存する必要はありませんが、実際には避けたいのですが、複雑であればデータベースに残っていれば問題ありません。

誰でもお手伝いできますか?

+0

関数を作成する必要がない場合は、匿名コードブロックを実行する['DO'](https://www.postgresql.org/docs/current/static/sql-do.html)文を読んでください:) –

答えて

1

データベース内の関数を作成しないようにしたい場合は、実際の代わりにPL/pgSQLのコードのpsqlの変数を使用して、それを行う方が簡単です:

\set owner 'MyDefaultOrganisation' 
\set ON_ERROR_STOP 1 
-- Let's open a transaction, so we do all or nothing 
BEGIN; 
    -- Execute the query and set variables with the output using \gset 
    SELECT id AS device_id 
    FROM device dev 
    WHERE dev.device_identification = :'device_identification' \gset 

    SELECT id AS owner_id 
    FROM owners own 
    WHERE own.owner_identification = :'owner' \gset 

    DELETE FROM device_authorization 
    WHERE device = :'device_id' AND owner = :'owner_id'; 

    INSERT INTO device_authorization(id, creation_time, device, owner) 
    VALUES (nextval('device_authorization_id_seq'), current_timestamp, :'device_id', :'owner_id'); 
COMMIT; 

その後、あなたはそれと実行を保存することができますあなたも、単一のステートメントとしてそれをすべて書き換えることができ

psql -d my_database -f ChangeOwnership.sql -v device_identification='TestDevice' 

CTEs (Common Table Expression)を使用して::

WITH dev_own AS (
    SELECT dev.id AS device_id, own.id AS owner_id 
    FROM device dev, owner own 
    WHERE 
     dev.device_identification = :'device_identification' 
     AND own.owner_identification = :'owner' 
), insert_new AS (
    INSERT INTO device_authorization(id, creation_time, device, owner) 
    SELECT nextval('device_authorization_id_seq'), current_timestamp, device_id, owner_id 
    FROM dev_own; 
) 
DELETE FROM device_authorization 
WHERE (device, owner) IN (SELECT device_id, owner_id FROM dev_own); 
前に試したとおりに
+0

パラメータ\ gsetが不明なのでファイルを実行できませんでしたが、それがなくてもすべてうまく動作します!お手伝いありがとう! – Joetjah

+0

@Joetjah \ gsetは、PostgreSQL 9.3以降、多少新しいものです。 2番目のバージョンは9.1以降で動作するはずです – MatheusOl

1

SELECTステートメントをSQLスクリプトに含めなかったため、関数が呼び出されません。そこには文が1つしかありません(CREATE FUNCTION)、それが正式に実行されます。後でその関数を取り除きたい場合は、SQLスクリプトにDROP FUNCTIONステートメントも必要です。

しかし、あなたの関数は何も意味を持ちませんので、代わりにDO statementを使用することをお勧めします。こうすることで、関数を定義することなくPL/pgSQLコードを実行することができます。

関連する問題