Wie verwendet man Variablen in einem einfachen PostgreSQL-Skript?


Antworten:


131

Die vollständige Antwort finden Sie in der offiziellen PostgreSQL-Dokumentation .

Sie können die neue Funktion zum Blockieren des anonymen PG9.0-Codes verwenden ( http://www.postgresql.org/docs/9.1/static/sql-do.html ).

DO $$
DECLARE v_List TEXT;
BEGIN
  v_List := 'foobar' ;
  SELECT *
  FROM   dbo.PubLists
  WHERE  Name = v_List;
  -- ...
END $$;

Sie können auch die letzte Einfügungs- ID erhalten:

DO $$
DECLARE lastid bigint;
BEGIN
  INSERT INTO test (name) VALUES ('Test Name') 
  RETURNING id INTO lastid;

  SELECT * FROM test WHERE id = lastid;
END $$;

7
(Und vergessen Sie nicht , die ;nach END $$, etwa so: END $$;.)
KajMagnus

3
ARBEITET NICHT FÜR MICH FEHLER IN DER NÄHE VON DO, ich habe auch einige Funktionen zwischen Anfang und Ende mit der Sprache plpgsql.
Ash

49
Der Code in diesem Beispiel funktioniert nicht. ERROR: query has no destination for result data HINT: If you want to discard the results of a SELECT, use PERFORM instead. CONTEXT: PL/pgSQL function inline_code_block line 7 at SQL statement
Jasen

1
Da ich für PostgreSQL völlig neu bin, habe ich eine Weile lang folgende Tipps erhalten: + Stellen Sie sicher, dass Sie Ihre Aussagen mit einem Semikolon beenden! + Da es keine Variablenkennung gibt, möchten Sie möglicherweise ein _ oder ähnliches verwenden, um mehrdeutige Spaltennamen zu vermeiden. + Sie können die Variable auf einen Zeilenwert setzen, indem Sie wie folgt DECLARE _accountid INT: = 1;
Der Coder

1
arbeite nicht für mich Mit Eichhörnchen. Fehler: FEHLER: nicht abgeschlossene Zeichenfolge in US-Dollar bei oder in der Nähe von "$$
Oliver Watkins

39
DO $$
DECLARE  
   a integer := 10;  
   b integer := 20;  
   c integer;  
BEGIN  
   c := a + b;
    RAISE NOTICE'Value of c: %', c;
END $$;

3
arbeite nicht für mich Mit Eichhörnchen. Fehler: FEHLER: nicht abgeschlossene Zeichenfolge in US-Dollar bei oder in der Nähe von "$$
Oliver Watkins

Es hat eine Weile gedauert, bis ich herausgefunden habe, dass Sie der Variablen nicht: wie bei anderen Variablen ein Präfix voranstellen dürfen , um sie zu verwenden . @ achilles-ram-nakirekanti könnten Sie ein Beispiel hinzufügen, indem Sie dies in einer selectAnweisung verwenden, um dies klarer zu machen?
Exhuma

28

Sie können verwenden:

\set list '''foobar'''
SELECT * FROM dbo.PubLists WHERE name = :list;

Das wird reichen


3
FEHLER: Syntaxfehler bei oder in der Nähe von "\" Was fehlt mir?
scw

14
@scw Dies ist nur über die psqlKonsole verfügbar . Sie können dies nicht in SQL Ihrer App schreiben.
Owensmartin

@owensmartin Sie können dies verwenden, ist alles, was zu psql weitergeleitet wird .. oder jedes Skript, das psql liest ...
Evan Carroll

4
Dies beantwortet die Frage überhaupt nicht. In MS SQL können Sie eine Variable in einer Abfrage definieren und genau dort im selben Tool verwenden. Ich verstehe nicht, warum die Leute dies in jeder Version dieser Frage als Antwort vorschlagen.
Stein

@stone anscheinend, weil dies ein großer "Miss" ist postgresqlund es die am wenigsten schlimmste Alternative ist. Im Allgemeinen war ich ziemlich zufrieden mit postgresql: aber dies ist ein überraschend großer Fehler
Javadba

10

Hier ist ein Beispiel für die Verwendung einer Variablen in plpgsql:

create table test (id int);
insert into test values (1);
insert into test values (2);
insert into test values (3);

create function test_fn() returns int as $$
    declare val int := 2;
    begin
        return (SELECT id FROM test WHERE id = val);
    end;
$$ LANGUAGE plpgsql;

SELECT * FROM test_fn();
 test_fn 
---------
       2

Weitere Informationen finden Sie in den plpgsql-Dokumenten .


4

Ich bin auf einige andere Dokumente gestoßen, die sie verwenden \set zum Deklarieren von Skriptvariablen verwendet werden, aber der Wert scheint wie ein konstanter Wert zu sein, und ich finde heraus, wie sich eine Variable und keine konstante Variable verhalten kann.

Ex:

\set Comm 150

select sal, sal+:Comm from emp

Hier salist der Wert, der in der Tabelle 'emp' vorhanden ist und commder konstante Wert ist.


2

Ich musste so etwas tun

CREATE OR REPLACE FUNCTION MYFUNC()
RETURNS VOID AS $$
DO
$do$
BEGIN
DECLARE
 myvar int;
 ...
END
$do$
$$ LANGUAGE SQL;

2

Postgresql hat keine nackten Variablen, Sie könnten eine temporäre Tabelle verwenden. Variablen sind nur in Codeblöcken oder als Benutzeroberflächenfunktion verfügbar.

Wenn Sie eine nackte Variable benötigen, können Sie eine temporäre Tabelle verwenden:

CREATE TEMP TABLE list AS VALUES ('foobar');

SELECT dbo.PubLists.*
FROM   dbo.PubLists,list
WHERE  Name = list.column1;

Als Nebeneffekt ist dieser Ansatz datenbankunabhängig, wodurch Ihre Tests im gesamten Backend portabler werden.
Bischof

2

Aufbauend auf der Antwort von @ nad2000 und der Antwort von @ Pavel hier landete ich hier für meine Flyway-Migrationsskripte. Behandlung von Szenarien, in denen das Datenbankschema manuell geändert wurde.

DO $$
BEGIN
    IF NOT EXISTS(
        SELECT TRUE FROM pg_attribute 
        WHERE attrelid = (
            SELECT c.oid
            FROM pg_class c
            JOIN pg_namespace n ON n.oid = c.relnamespace
            WHERE 
                n.nspname = CURRENT_SCHEMA() 
                AND c.relname = 'device_ip_lookups'
            )
        AND attname = 'active_date'
        AND NOT attisdropped
        AND attnum > 0
        )
    THEN
        RAISE NOTICE 'ADDING COLUMN';        
        ALTER TABLE device_ip_lookups
            ADD COLUMN active_date TIMESTAMP;
    ELSE
        RAISE NOTICE 'SKIPPING, COLUMN ALREADY EXISTS';
    END IF;
END $$;


1

Für die Verwendung von Variablen in beispielsweise alter table:

DO $$ 
DECLARE name_pk VARCHAR(200);
BEGIN
select constraint_name
from information_schema.table_constraints
where table_schema = 'schema_name'
      and table_name = 'table_name'
      and constraint_type = 'PRIMARY KEY' INTO name_pk;
IF (name_pk := '') THEN
EXECUTE 'ALTER TABLE schema_name.table_name DROP CONSTRAINT ' || name_pk;
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.