例如,在 MS-SQL 中,您可以打开查询窗口并运行以下命令:
DECLARE @List AS VARCHAR(8)
SELECT @List = 'foobar'
SELECT *
FROM dbo.PubLists
WHERE Name = @List
这在 PostgreSQL 中是如何完成的?可以做吗?
完整的答案位于官方 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 $$;
您还可以获得最后一个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 $$;
DO $$
DECLARE
a integer := 10;
b integer := 20;
c integer;
BEGIN
c := a + b;
RAISE NOTICE'Value of c: %', c;
END $$;
您可以使用:
\set list '''foobar'''
SELECT * FROM dbo.PubLists WHERE name = :list;
这样就可以了
这是在 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 文档以获取更多信息。
我遇到过一些其他文档,他们使用
\set
来声明脚本变量,但该值似乎是常量值,我正在寻找可以充当变量而不是常量变量的方法。
例如:
\set Comm 150
select sal, sal+:Comm from emp
这里
sal
是表“emp”中存在的值,comm
是常量值。
Postgresql 没有裸变量,您可以使用临时表。 变量仅在代码块中或作为用户界面功能可用。
如果您需要一个裸变量,您可以使用临时表:
CREATE TEMP TABLE list AS VALUES ('foobar');
SELECT dbo.PubLists.*
FROM dbo.PubLists,list
WHERE Name = list.column1;
基于@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 $$;
例如在更改表中使用变量:
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;
我必须做这样的事情
CREATE OR REPLACE FUNCTION MYFUNC()
RETURNS VOID AS $$
DO
$do$
BEGIN
DECLARE
myvar int;
...
END
$do$
$$ LANGUAGE SQL;
您还可以简单地创建一个在实际查询中使用的常量查询:
WITH vars as (SELECT 'foobar' AS list)
SELECT *
FROM dbo.PubLists, vars
WHERE Name = vars.list
鉴于受欢迎程度和有些不完整的答案,我将提供两种解决方案。
下面我将使用一个过度烘焙的示例,将右下角“blurb”上的推文更新为“hello world”。
id(序列号) | pub_id(文本) | 推文(文本) |
---|---|---|
1 | abc | 世界你好 |
2 | 定义 | 宣传 |
一个简单的 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 |
--------------------------------------------------
*/
*备注:
我的文章详细解释了如何在 PL/pgSQL 函数中的 DECLARE 子句中声明局部变量。
您可以在
:=
子句中使用 =
、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
$$;
*备注:
:=
、=
和 DEFAULT
是相同的。value4
会出错。value5
是NULL
。DECLARE
语句中使用 DO
子句声明局部变量。