Làm thế nào để bạn sử dụng các biến trong một kịch bản PostgreSQL đơn giản?


Câu trả lời:


131

Câu trả lời đầy đủ nằm trong tài liệu PostgreSQL chính thức .

Bạn có thể sử dụng tính năng chặn mã ẩn danh PG9.0 mới ( 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 $$;

Ngoài ra, bạn có thể lấy id chèn cuối cùng :

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

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

7
(Và đừng quên ;sau END $$, như vậy: END $$;.)
KajMagnus

3
KHÔNG LÀM VIỆC CHO TÔI GẦN LỖI, tôi cũng có một số chức năng giữa phần bắt đầu và kết thúc bằng ngôn ngữ plpgsql.
Ash

49
mã trong ví dụ này không hoạt động. 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
Việc hoàn toàn mới đối với PostgreSQL, điều này đã khiến tôi mất một thời gian, đây là một số mẹo khác: + Đảm bảo bạn kết thúc câu lệnh của mình bằng dấu chấm phẩy! + Vì không có định danh biến, bạn có thể muốn sử dụng dấu _ hoặc một cái gì đó tương tự để tránh tên cột không rõ ràng. + Bạn có thể đặt biến thành một giá trị trong dòng bằng cách sử dụng như sau DECLARE _accountid INT: = 1;
The Coder

1
không làm việc cho tôi. Sử dụng sóc. Lỗi: LỖI: chuỗi được trích dẫn bằng đô la chưa kết thúc tại hoặc gần "$$
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
không làm việc cho tôi. Sử dụng sóc. Lỗi: LỖI: chuỗi được trích dẫn bằng đô la chưa kết thúc tại hoặc gần "$$
Oliver Watkins

Tôi mất một thời gian để tìm ra rằng để sử dụng biến, bạn không được đặt trước nó bằng một :như với các biến khác. @ achilles-ram-nakirekanti bạn có thể thêm một ví dụ bằng cách sử dụng điều này trong một selectcâu lệnh để làm rõ hơn điều này không?
exhuma

28

Bạn có thể dùng:

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

Điều đó sẽ làm


3
LỖI: lỗi cú pháp tại hoặc gần "\" Tôi đang thiếu gì?
scw

14
@scw Điều này chỉ có sẵn từ psqlbảng điều khiển. Bạn sẽ không thể viết điều này trong SQL của ứng dụng của bạn.
owensmartin

@owensmartin Bạn sẽ có thể sử dụng đây là bất kỳ thứ gì được chuyển đến psql .. hoặc bất kỳ tập lệnh nào mà psql đọc được ...
Evan Carroll

4
Điều này không trả lời câu hỏi nào cả. Trong MS SQL, bạn có thể định nghĩa một var trong một truy vấn và sử dụng nó ngay tại đó, trong cùng một công cụ. Tôi không hiểu tại sao mọi người tiếp tục đề xuất đây như một câu trả lời, trong mọi phiên bản của câu hỏi này.
stone

@stone rõ ràng là bởi vì đây là một "bỏ lỡ" rất lớn postgresqlvà nó là sự thay thế ít tồi tệ nhất. nói chung tôi khá hài lòng với postgresql: nhưng đây là một thất bại lớn đáng ngạc nhiên
javadba

10

Đây là một ví dụ về việc sử dụng một biến trong 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

Hãy xem tài liệu plpgsql để biết thêm thông tin.


4

Tôi đã xem qua một số tài liệu khác mà họ sử dụng \setđể khai báo biến kịch bản nhưng giá trị dường như giống như giá trị không đổi và tôi đang tìm cách có thể hoạt động như một biến chứ không phải một biến hằng số.

Ví dụ:

\set Comm 150

select sal, sal+:Comm from emp

Đây sallà giá trị có trong bảng 'emp' và commlà giá trị không đổi.


2

Tôi đã phải làm một cái gì đó như thế này

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

2

Postgresql không có các biến trống, bạn có thể sử dụng một bảng tạm thời. biến chỉ có sẵn trong các khối mã hoặc như một tính năng giao diện người dùng.

Nếu bạn cần một biến trống, bạn có thể sử dụng bảng tạm thời:

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

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

Như một lợi ích phụ, cách tiếp cận này là bất khả tri đối với cơ sở dữ liệu, làm cho các thử nghiệm của bạn dễ di động hơn trên phần phụ trợ.
giám mục

2

Dựa trên câu trả lời của @ nad2000 và câu trả lời của @ Pavel ở đây , đây là nơi tôi đã kết thúc cho các tập lệnh di chuyển Flyway của mình. Xử lý các tình huống trong đó lược đồ cơ sở dữ liệu được sửa đổi theo cách thủ công.

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

Để sử dụng các biến trong bảng thay đổi ví dụ:

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;
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.