将查询作为参数传递时找不到变量
Doesn't find variable when passing query as parameter
我有一个带有静态输出的函数可以正常工作。 (Postgres v.10)
这 returns 每个服务器的用户数量。
代码如下:
CREATE OR REPLACE FUNCTION public.test()
RETURNS SETOF record
LANGUAGE plpgsql
AS $function$
DECLARE
var_req TEXT;
var_error text;
rec_key record;
cur_key CURSOR FOR Select s.srv,s.host,s.port from public.connections() s where s.online = true;
BEGIN
open cur_key;
loop
fetch cur_key into rec_key;
EXIT WHEN NOT FOUND;
var_req :=
'Select * from dblink(
''host=' || rec_key.host || '
port=' || rec_key.port || '
user=**
password=**
dbname=mydb'',
''
select '''''|| rec_key.srv ||''''' as srv ,count (*) as total from users '') as (srv varchar,total integer)
';
return query execute var_req;
end loop;
close cur_key;
END
$function$
;
输出=
srv total
rp1 50
sr2 41
xy 100
为了能够重用此查询,我想移出 sql 部分,以便我可以将其作为参数传递。
CREATE OR REPLACE FUNCTION public.test2(text)
RETURNS SETOF record
LANGUAGE plpgsql
AS $function$
DECLARE
var_req TEXT;
var_error text;
rec_key record;
cur_key CURSOR FOR Select s.srv,s.host,s.port from public.connections() s where s.online = true;
BEGIN
open cur_key;
loop
fetch cur_key into rec_key;
EXIT WHEN NOT FOUND;
var_req :=
'Select * from dblink(
''host=' || rec_key.host || '
port=' || rec_key.port || '
user=**
password=**
dbname=**'',
''
' || || '
';
return query execute var_req;
end loop;
close cur_key;
END
$function$
;
现在,当我尝试使用动态函数进行完全相同的查询时,我无法使用它。
像这样,我非常接近我的目标,但我没有使用 rec_key.srv 变量中的内容,而是 returns '''''|| rec_key.srv ||''''' :(
select * from public.test2('select ''''''''''''|| rec_key.srv ||'''''''''''' as srv ,count (*) as total from users '') as (srv varchar,total integer)') as (srv varchar,total integer)
输出=
srv total
'''''|| rec_key.srv ||''''' 50
'''''|| rec_key.srv ||''''' 41
'''''|| rec_key.srv ||''''' 100
谁能告诉我如何用新函数调用变量 rec_key.srv 中的内容?
归结为:(!)
SELECT s.srv, t.*
FROM public.connections() s
, dblink('host=' || s.host || ' port=' || s.port || ' user=** password=** dbname=**'
, 'SELECT count(*) FROM users') AS t(total integer);
没有包装函数,没有动态 SQL,没有游标。
只需在隐式 CROSS JOIN LATERAL
.
中执行 dblink()
我还在结果中添加了 srv
,就像您在第一个函数中所做的那样。无需通过 dblink 进行管道传输。
参见:
传递任意查询对SQL注入开放。请务必了解可能的影响,并仅在受信任的输入下执行。参见:
我有一个带有静态输出的函数可以正常工作。 (Postgres v.10) 这 returns 每个服务器的用户数量。
代码如下:
CREATE OR REPLACE FUNCTION public.test()
RETURNS SETOF record
LANGUAGE plpgsql
AS $function$
DECLARE
var_req TEXT;
var_error text;
rec_key record;
cur_key CURSOR FOR Select s.srv,s.host,s.port from public.connections() s where s.online = true;
BEGIN
open cur_key;
loop
fetch cur_key into rec_key;
EXIT WHEN NOT FOUND;
var_req :=
'Select * from dblink(
''host=' || rec_key.host || '
port=' || rec_key.port || '
user=**
password=**
dbname=mydb'',
''
select '''''|| rec_key.srv ||''''' as srv ,count (*) as total from users '') as (srv varchar,total integer)
';
return query execute var_req;
end loop;
close cur_key;
END
$function$
;
输出=
srv total
rp1 50
sr2 41
xy 100
为了能够重用此查询,我想移出 sql 部分,以便我可以将其作为参数传递。
CREATE OR REPLACE FUNCTION public.test2(text)
RETURNS SETOF record
LANGUAGE plpgsql
AS $function$
DECLARE
var_req TEXT;
var_error text;
rec_key record;
cur_key CURSOR FOR Select s.srv,s.host,s.port from public.connections() s where s.online = true;
BEGIN
open cur_key;
loop
fetch cur_key into rec_key;
EXIT WHEN NOT FOUND;
var_req :=
'Select * from dblink(
''host=' || rec_key.host || '
port=' || rec_key.port || '
user=**
password=**
dbname=**'',
''
' || || '
';
return query execute var_req;
end loop;
close cur_key;
END
$function$
;
现在,当我尝试使用动态函数进行完全相同的查询时,我无法使用它。 像这样,我非常接近我的目标,但我没有使用 rec_key.srv 变量中的内容,而是 returns '''''|| rec_key.srv ||''''' :(
select * from public.test2('select ''''''''''''|| rec_key.srv ||'''''''''''' as srv ,count (*) as total from users '') as (srv varchar,total integer)') as (srv varchar,total integer)
输出=
srv total
'''''|| rec_key.srv ||''''' 50
'''''|| rec_key.srv ||''''' 41
'''''|| rec_key.srv ||''''' 100
谁能告诉我如何用新函数调用变量 rec_key.srv 中的内容?
归结为:(!)
SELECT s.srv, t.*
FROM public.connections() s
, dblink('host=' || s.host || ' port=' || s.port || ' user=** password=** dbname=**'
, 'SELECT count(*) FROM users') AS t(total integer);
没有包装函数,没有动态 SQL,没有游标。
只需在隐式 CROSS JOIN LATERAL
.
我还在结果中添加了 srv
,就像您在第一个函数中所做的那样。无需通过 dblink 进行管道传输。
参见:
传递任意查询对SQL注入开放。请务必了解可能的影响,并仅在受信任的输入下执行。参见: