คุณใช้ตัวแปรในสคริปต์ PostgreSQL อย่างง่ายได้อย่างไร


103

ตัวอย่างเช่นใน MS-SQL คุณสามารถเปิดหน้าต่างแบบสอบถามและเรียกใช้สิ่งต่อไปนี้:

DECLARE @List AS VARCHAR(8)

SELECT @List = 'foobar'

SELECT *
FROM   dbo.PubLists
WHERE  Name = @List

สิ่งนี้ทำได้อย่างไรใน PostgreSQL มันสามารถทำได้?


1
คำถามที่เกี่ยวข้อง: stackoverflow.com/q/1490942/330315และstackoverflow.com/q/13316773/330315
a_horse_with_no_name

คำตอบ:


135

คำตอบที่สมบูรณ์ตั้งอยู่ในเอกสาร PostgreSQL อย่างเป็นทางการ

คุณสามารถใช้คุณลักษณะบล็อกโค้ดแบบไม่ระบุชื่อ PG9.0 ใหม่ได้ ( 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 $$;

นอกจากนี้คุณจะได้รับรหัสแทรกล่าสุด:

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

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

7
(และอย่าลืม;หลังจากEND $$นั้น: END $$;.)
KajMagnus

3
ไม่ทำงานสำหรับฉันข้อผิดพลาดใกล้เคียงฉันยังมีฟังก์ชั่นบางอย่างระหว่างจุดเริ่มต้นและจุดสิ้นสุดด้วยภาษา plpgsql
เถ้า

53
รหัสในตัวอย่างนี้ใช้ไม่ได้ 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
การเพิ่งเริ่มใช้ PostgreSQL เป็นเรื่องใหม่ทำให้ฉันต้องใช้เวลาสักพักนี่คือเคล็ดลับเพิ่มเติม: + ตรวจสอบให้แน่ใจว่าคุณจบงบด้วยอัฒภาค + เนื่องจากไม่มีตัวระบุตัวแปรคุณอาจต้องการใช้ _ หรือสิ่งที่คล้ายกันเพื่อหลีกเลี่ยงชื่อคอลัมน์ที่ไม่ชัดเจน + คุณสามารถตั้งค่าตัวแปรให้เป็นค่าในบรรทัดโดยใช้เช่น DECLARE _accountid INT นี้: = 1;
The Coder

1
อย่าทำงานให้ฉัน การใช้กระรอก ข้อผิดพลาด: ข้อผิดพลาด: สตริงที่เสนอราคาดอลลาร์ที่ยังไม่สิ้นสุดที่หรือใกล้ "$$
Oliver Watkins

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

4
อย่าทำงานให้ฉัน การใช้กระรอก ข้อผิดพลาด: ข้อผิดพลาด: สตริงที่เสนอราคาดอลลาร์ที่ยังไม่สิ้นสุดที่หรือใกล้ "$$
Oliver Watkins

1
ฉันใช้เวลาสักพักหนึ่งเพื่อหาคำตอบว่าในการใช้ตัวแปรคุณต้องไม่นำหน้ามันด้วย a :เหมือนกับตัวแปรอื่น ๆ @ achilles-ram-nakirekanti คุณสามารถเพิ่มตัวอย่างโดยใช้สิ่งนี้ในselectคำสั่งเพื่อให้ชัดเจนขึ้น?
exhuma

27

คุณสามารถใช้ได้:

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

ที่จะทำ


3
ข้อผิดพลาด: ข้อผิดพลาดทางไวยากรณ์ที่หรือใกล้ "\" ฉันขาดอะไรไป
scw

14
@scw สิ่งนี้สามารถใช้ได้จากpsqlคอนโซลเท่านั้น คุณจะเขียนสิ่งนี้ใน SQL ของแอปไม่ได้
owensmartin

@owensmartin คุณจะสามารถใช้สิ่งนี้คืออะไรก็ได้ที่ส่งผ่านไปยัง psql .. หรือสคริปต์ใด ๆ ที่ psql อ่าน ...
Evan Carroll

4
นี่ไม่ตอบคำถามเลย ใน MS SQL คุณสามารถกำหนด var ในแบบสอบถามและใช้ที่นั่นได้ในเครื่องมือเดียวกัน ฉันไม่เข้าใจว่าทำไมผู้คนถึงเสนอสิ่งนี้เป็นคำตอบในคำถามนี้ทุกเวอร์ชัน
หิน

เห็นได้ชัดว่า @stone เป็นเพราะนี่คือ "พลาด" อย่างมากpostgresqlและเป็นทางเลือกที่แย่ที่สุด โดยทั่วไปฉันค่อนข้างพอใจกับpostgresql: แต่นี่เป็นความล้มเหลวที่ยิ่งใหญ่อย่างน่าประหลาดใจ
Javadba

10

นี่คือตัวอย่างของการใช้ตัวแปรใน 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

ดูเอกสาร plpgsqlสำหรับข้อมูลเพิ่มเติม


4

ฉันเจอเอกสารอื่น ๆ ที่ใช้\setในการประกาศตัวแปรสคริปต์ แต่ค่าดูเหมือนจะเป็นค่าคงที่และฉันกำลังหาวิธีที่สามารถทำหน้าที่เหมือนตัวแปรไม่ใช่ตัวแปรคงที่

เช่น:

\set Comm 150

select sal, sal+:Comm from emp

นี่salคือค่าที่มีอยู่ในตาราง 'emp' และcommเป็นค่าคงที่


2

ฉันต้องทำอะไรแบบนี้

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

2

Postgresql ไม่มีตัวแปรเปล่าคุณสามารถใช้ตารางชั่วคราว ตัวแปรสามารถใช้ได้เฉพาะในบล็อกโค้ดหรือเป็นคุณสมบัติอินเทอร์เฟซผู้ใช้

หากคุณต้องการตัวแปรเปล่าคุณสามารถใช้ตารางชั่วคราว:

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

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

แนวทางนี้เป็นประโยชน์ต่อฐานข้อมูลทำให้การทดสอบของคุณพกพาได้ง่ายขึ้นในแบ็กเอนด์
อธิการ

2

จากคำตอบของ @ nad2000 และคำตอบของ@ Pavel ที่นี่นี่คือที่ที่ฉันลงเอยด้วยสคริปต์การย้าย Flyway ของฉัน การจัดการสำหรับสถานการณ์ที่สคีมาฐานข้อมูลถูกแก้ไขด้วยตนเอง

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

สำหรับตัวแปรที่ใช้ในตัวอย่างเช่น 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;
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.