如何在简单的 PostgreSQL 脚本中使用变量?

发布于 2024-07-17 13:05:56 字数 249 浏览 5 评论 0原文

例如,在 MS-SQL 中,您可以打开一个查询窗口并运行以下命令:

DECLARE @List AS VARCHAR(8)
    
SELECT @List = 'foobar'
    
SELECT * FROM dbo.PubLists WHERE Name = @List

在 PostgreSQL 中这是如何完成的? 能做到吗?

For example, in MS-SQL, you can open up a query window and run the following:

DECLARE @List AS VARCHAR(8)
    
SELECT @List = 'foobar'
    
SELECT * FROM dbo.PubLists WHERE Name = @List

How is this done in PostgreSQL? Can it be done?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

荆棘i 2024-07-24 13:05:56

完整的答案位于官方 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 $;

您也可以获取最后一个 插入 ID:

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

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

Complete answer is located in the official PostgreSQL documentation.

You can use new PG9.0 anonymous code block feature (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 $;

Also you can get the last insert id:

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

  SELECT * FROM test WHERE id = lastid;
END $;
っ左 2024-07-24 13:05:56
DO $
DECLARE  
   a integer := 10;  
   b integer := 20;  
   c integer;  
BEGIN  
   c := a + b;
    RAISE NOTICE'Value of c: %', c;
END $;
DO $
DECLARE  
   a integer := 10;  
   b integer := 20;  
   c integer;  
BEGIN  
   c := a + b;
    RAISE NOTICE'Value of c: %', c;
END $;
ヤ经典坏疍 2024-07-24 13:05:56

你可以使用:

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

这样就可以了

You can use:

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

That will do

渡你暖光 2024-07-24 13:05:56

以下是在 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 文档 了解更多信息。

Here's an example of using a variable 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

Have a look at the plpgsql docs for more information.

月朦胧 2024-07-24 13:05:56

我遇到过一些其他文档,它们使用 \set 来声明脚本变量,但该值似乎像常量值,我正在寻找可以充当变量而不是变量的方法常数变量。

例如:

\set Comm 150

select sal, sal+:Comm from emp

这里 sal 是表“emp”中存在的值,comm 是常量值。

I've came across some other documents which they use \set to declare scripting variable but the value is seems to be like constant value and I'm finding for way that can be acts like a variable not a constant variable.

Ex:

\set Comm 150

select sal, sal+:Comm from emp

Here sal is the value that is present in the table 'emp' and comm is the constant value.

拒绝两难 2024-07-24 13:05:56

Postgresql 没有裸变量,您可以使用临时表。
变量仅在代码块中或作为用户界面功能可用。

如果您需要一个裸变量,您可以使用临时表:

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

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

Postgresql does not have bare variables, you could use a temporary table.
variables are only available in code blocks or as a user-interface feature.

If you need a bare variable you could use a temporary table:

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

SELECT dbo.PubLists.*
FROM   dbo.PubLists,list
WHERE  Name = list.column1;
过度放纵 2024-07-24 13:05:56

基于 @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 $;

Building on @nad2000's answer and @Pavel's answer here, this is where I ended up for my Flyway migration scripts. Handling for scenarios where the database schema was manually modified.

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 $;
魔法唧唧 2024-07-24 13:05:56

例如,在 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;

For use variables in for example 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;
梦过后 2024-07-24 13:05:56

我不得不做这样的事情

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

I had to do something like this

CREATE OR REPLACE FUNCTION MYFUNC()
RETURNS VOID AS $
DO
$do$
BEGIN
DECLARE
 myvar int;
 ...
END
$do$
$ LANGUAGE SQL;
宫墨修音 2024-07-24 13:05:56

您还可以简单地创建一个在实际查询中使用的常量查询:

WITH vars as (SELECT 'foobar' AS list) 
SELECT *
FROM   dbo.PubLists, vars
WHERE  Name = vars.list

You can also simply make a constant query that you use in the actual query:

WITH vars as (SELECT 'foobar' AS list) 
SELECT *
FROM   dbo.PubLists, vars
WHERE  Name = vars.list
时光是把杀猪刀 2024-07-24 13:05:56

鉴于受欢迎程度和有些不完整的答案,我将提供两种解决方案。

  1. 不会返回行的 do 块。 您可以使用事务游标返回行,但这有点混乱。
  2. 一个函数(返回行)

下面我将使用一个过度烘焙的示例,将右下角“blurb”上的推文更新为“hello world”。

id (serial)pub_id (text)tweet (text)
1abchello world
2defblurb

一个简单的 do 块

do $
declare
    src_pub_id text;
    dst_pub_id text;
    src_id    int; 
    dest_id   int;
    src_tweet text;
begin
    src_pub_id := 'abc';
    dst_pub_id := 'def';
    
    -- query result into a temp variable
    src_id := (select id from tweets where pub_id = src_pub_id);

    -- query result into a temp variable (another way)
    select tweet into src_tweet from tweets where id = src_id;

    dest_id := (select id from tweets where pub_id = dst_pub_id);
    update tweets set tweet=src_tweet where id = dest_id;
end $ language plpgsql; -- need the language to avoid ERROR 42P13

一个函数

create or replace function sync_tweets(
    src_pub_id text, -- function arguments
    dst_pub_id text
) returns setof tweets as -- i.e. rows. int, text work too
$
declare
    src_id    int; -- temp function variables (not args)
    dest_id   int;
    src_tweet text;
begin
    -- query result into a temp variable
    src_id := (select id from tweets where pub_id = src_pub_id);

    -- query result into a temp variable (another way)
    select tweet into src_tweet from tweets where id = src_id;

    dest_id := (select id from tweets where pub_id = dst_pub_id);
    update tweets set tweet=src_tweet where id = dest_id;

    return query -- i.e. rows, return 0 with return int above works too
        select * from tweets where pub_id in (src_pub_id, dst_pub_id);
end
$ language plpgsql; -- need the language to avoid ERROR 42P13

-- Run it!
select * from sync_tweets('abc', 'def');

-- Optional drop if you don't want the db to keep your function
drop function if exists sync_tweets(text, text);

/*
  Outputs
   __________________________________________________ 
  |  id (serial)  |  pub_id (text)  |  tweet (text)  |
  |---------------|-----------------|----------------|
  |  1            |  abc            |  hello world   |
  |  2            |  def            |  blurb         |
  --------------------------------------------------
*/

Given the popularity, and somewhat incomplete answers I'll provide two solutions.

  1. A do block that won't return rows. You can return rows with a transaction cursor, but it's a bit messy.
  2. A function (that returns rows)

Below I'll use an over-baked example of updating the tweet on the bottom right "blurb" with "hello world".

id (serial)pub_id (text)tweet (text)
1abchello world
2defblurb

A simple do block

do $
declare
    src_pub_id text;
    dst_pub_id text;
    src_id    int; 
    dest_id   int;
    src_tweet text;
begin
    src_pub_id := 'abc';
    dst_pub_id := 'def';
    
    -- query result into a temp variable
    src_id := (select id from tweets where pub_id = src_pub_id);

    -- query result into a temp variable (another way)
    select tweet into src_tweet from tweets where id = src_id;

    dest_id := (select id from tweets where pub_id = dst_pub_id);
    update tweets set tweet=src_tweet where id = dest_id;
end $ language plpgsql; -- need the language to avoid ERROR 42P13

A function

create or replace function sync_tweets(
    src_pub_id text, -- function arguments
    dst_pub_id text
) returns setof tweets as -- i.e. rows. int, text work too
$
declare
    src_id    int; -- temp function variables (not args)
    dest_id   int;
    src_tweet text;
begin
    -- query result into a temp variable
    src_id := (select id from tweets where pub_id = src_pub_id);

    -- query result into a temp variable (another way)
    select tweet into src_tweet from tweets where id = src_id;

    dest_id := (select id from tweets where pub_id = dst_pub_id);
    update tweets set tweet=src_tweet where id = dest_id;

    return query -- i.e. rows, return 0 with return int above works too
        select * from tweets where pub_id in (src_pub_id, dst_pub_id);
end
$ language plpgsql; -- need the language to avoid ERROR 42P13

-- Run it!
select * from sync_tweets('abc', 'def');

-- Optional drop if you don't want the db to keep your function
drop function if exists sync_tweets(text, text);

/*
  Outputs
   __________________________________________________ 
  |  id (serial)  |  pub_id (text)  |  tweet (text)  |
  |---------------|-----------------|----------------|
  |  1            |  abc            |  hello world   |
  |  2            |  def            |  blurb         |
  --------------------------------------------------
*/
放赐 2024-07-24 13:05:56

您可以在 DECLARE 子句中使用 :== 声明局部变量,如下所示:

DO $
DECLARE
  value1 INT := 1; -- Here
  value2 INT = 2; -- Here
  value3 INT DEFAULT 3; -- Here
  value4 CONSTANT INT := 4; -- Here
  value5 INT; -- Here
BEGIN
  RAISE INFO '%', value1 + value2 + value3; -- 6
END
$;

*Memos:

  • :==DEFAULT 是相同的。
  • 尝试更改常量局部变量 value4 会出错。
  • 未初始化的局部变量value5NULL
  • 您可以在 PL/pgSQL 函数和过程以及 DO 语句中使用 DECLARE 子句声明局部变量。

You can declare local variables with :=, = in DECLARE clause as shown below:

DO $
DECLARE
  value1 INT := 1; -- Here
  value2 INT = 2; -- Here
  value3 INT DEFAULT 3; -- Here
  value4 CONSTANT INT := 4; -- Here
  value5 INT; -- Here
BEGIN
  RAISE INFO '%', value1 + value2 + value3; -- 6
END
$;

*Memos:

  • :=, = and DEFAULT are the same.
  • Trying to change the constant local variable value4 gets error.
  • The uninitialized local variable value5 is NULL.
  • You can declare local variables with DECLARE clause in a PL/pgSQL function and procedure and DO statement.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文