2016-08-26 4 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. Тем не менее, функция получает хранится в базе данных, и я могу выполнить эту функцию (в pgAdmin) с помощью

SELECT "device_authorisation_change"('TestDevice'); 

На этот раз функция выполняет хорошо.

Что я хочу достичь, так это то, что я могу запустить sql-скрипт из командной строки, используя (named) аргументы, которые немедленно обновляют данные в базе данных. Нет необходимости сохранять функцию в базе данных, я действительно люблю ее избегать, но если это усложняет ситуацию, это не проблема, если она остается в базе данных.

Может ли кто-нибудь помочь мне?

+0

Читайте статью ['DO'] (https://www.postgresql.org/docs/current/static/sql-do.html), которая выполняет анонимный блок кода, если вам не нужно создавать функцию :) –

ответ

1

Если вы хотите, чтобы избежать создания функции в базе данных, то на самом деле проще сделать это с помощью psql «s переменные вместо кода PL/PgSQL:

\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. Вторая версия должна работать с 9.1 – MatheusOl

1

Ваша функция не вызывается, потому что вы не указали оператор SELECT в сценарии SQL. Там есть только одно заявление (CREATE FUNCTION), и оно выполнено надлежащим образом. Если вы хотите впоследствии избавиться от функции, вам также понадобится оператор DROP FUNCTION в сценарии SQL.

Но поскольку ваша функция не возвращает ничего значимого, я бы предположил, что вместо этого вы используете DO statement. Таким образом, вы можете выполнить код PL/pgSQL без необходимости определять функцию.

Смежные вопросы