假设我想查询一个带有几个WHERE
过滤器的大表。我正在使用 Postgres 11 和外部表;外部数据包装器 (FDW) 是clickhouse_fdw
. 但我也对通用解决方案感兴趣。
我可以这样做:
SELECT id,c1,c2,c3 from big_table where id=3 and c1=2
Run Code Online (Sandbox Code Playgroud)
我的 FDW 能够对远程外部数据源进行过滤,确保上述查询快速并且不会拉取太多数据。
如果我写的话上面的效果是一样的:
SELECT id,c1,c2,c3 from big_table where id IN (3,4,5) and c1=2
Run Code Online (Sandbox Code Playgroud)
即所有的过滤都被发送到下游。
但是,如果我尝试执行的过滤稍微复杂一些:
SELECT bt.id,bt.c1,bt.c2,bt.c3
from big_table bt
join lookup_table l on bt.id=l.id
where c1=2 and l.x=5
Run Code Online (Sandbox Code Playgroud)
然后查询规划器决定远程过滤c1=2
,但在本地应用另一个过滤器。
在我的用例中,先计算哪些id
s 有l.x=5
,然后将其发送出去进行远程过滤会快得多,所以我尝试按以下方式编写:
SELECT id,c1,c2,c3
from big_table
where c1=2
and id IN (select id from lookup_table where x=5)
Run Code Online (Sandbox Code Playgroud)
big_table
然而,查询规划器仍然决定在本地对satisfy的所有结果执行第二个过滤器c1=2
,这非常慢。
有什么方法可以“强制”(select …
sql postgresql sql-execution-plan postgresql-performance foreign-data-wrapper
我可以使用 PostgreSQL 的带美元引号的字符串常量安全地防止 SQL 注入吗?
我知道处理动态查询的最好方法是使用参数化查询在应用程序层中生成它们,这不是这个问题的内容。所有的业务逻辑都在存储过程中。
我有一个存储过程,它接受参数并生成查询、运行它、格式化结果并将其作为文本块返回。这个函数传递了一个表名、列名和 WHERE 参数。传递给函数的 WHERE 参数来自用户在数据库中输入的数据。我想确保对刺进行消毒,以便构建的查询是安全的。
使用 PostgreSQL 的美元引号字符串常量,我应该能够安全地清理除“ $$ ”之外的所有字符串输入。但是,如果我对 "$" 进行字符串替换以对其进行转义,我应该能够进行安全的字符串比较。
存储过程:
function_name(tablename text, colnames text[], whereparam text)
--Build dynamic query...
Run Code Online (Sandbox Code Playgroud)
函数调用:
SELECT
function_name('tablename', ARRAY['col1', 'col2', 'col3'], 'AND replace(col1, ''$'', ''/$'') = $$' || replace(alt_string_col, '$', '/$') || '$$ ')
FROM alttable
WHERE alt_id = 123;
Run Code Online (Sandbox Code Playgroud)
查询生成:
SELECT col1, col2, col3 FROM tablename WHERE 1=1 AND replace(col1, '$', '/$') = $$un/safe'user /$/$ data;$$
Run Code Online (Sandbox Code Playgroud)
由于我在将 col1 字段与转义的用户数据进行比较之前对其进行了转义,因此即使用户输入“un/safe'user $$ data;” 在字段 alt_string_col 中,双美元符号不会中断查询并且比较通过。
这是在 PostgreSQL …
我正在调整一些PL/pgSQL代码,所以我refcursor
可以将表名作为参数.因此我更改了以下行:
declare
pointCurs CURSOR FOR SELECT * from tableName for update;
Run Code Online (Sandbox Code Playgroud)
这一个:
OPEN pointCurs FOR execute 'SELECT * FROM ' || quote_ident(tableName) for update;
Run Code Online (Sandbox Code Playgroud)
我调整了循环,然后,循环经过了.现在在循环中的某个时刻我需要更新记录(由光标指向)并且我卡住了.我该如何正确调整以下代码行?
UPDATE tableName set tp_id = pos where current of pointCurs;
Run Code Online (Sandbox Code Playgroud)
我修改了tableName
和的引号,并在开头pos
添加了EXECUTE
子句,但是我得到了错误where current of pointCurs
.
(i)我如何更新记录?
(ii)该函数适用于来自公共模式的表,而来自其他模式的表(例如trace.myname)失败.
任何评论都非常感谢..
CREATE OR REPLACE FUNCTION getParentLtree(parent_id bigint, tbl_name varchar)
RETURNS ltree AS
$BODY$
DECLARE
parent_ltree ltree;
BEGIN
-- This works fine:
-- select into parent_ltree l_tree from tbl1 where id = parent_id;
EXECUTE format('select into parent_ltree l_tree from %I
where id = %I', tbl_name,parent_id);
RETURN parent_ltree;
END;
$BODY$ LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)
上述功能有2个问题:
parent_id
是integer
,但它会被替换引号?int
变量的正确格式说明符是什么?select into
不起作用EXECUTE
?如何使上面的注释查询使用表名传递?我有一个类似于以下的表:
CREATE TABLE stats (
name character varying(15),
q001001 numeric(9,0),
q001002 numeric(9,0),
q001003 numeric(9,0),
q001004 numeric(9,0),
q001005 numeric(9,0)
)
Run Code Online (Sandbox Code Playgroud)
我需要在这个表中查询各个字段的总和,如下所示:
SELECT sum(q001001) as total001,
sum(q001002) as total002,
sum(q001005) as total005,
FROM stats;
Run Code Online (Sandbox Code Playgroud)
这会产生一行数据和三列数据.
但是,出于报告目的,我需要以相反的方式列出结果.我需要三行和一列(好吧,实际上是两个,第一个是总和的字段),如下所示:
FieldName | SUM
----------+-------
q001001 | 12345
q001002 | 5432
q001005 | 986
Run Code Online (Sandbox Code Playgroud)
我想使用这样的一些SQL,其中field_name
(来自stats表中字段名称的查找表)用于子查询:
select l.field_name, (select sum(l.field_name) from stats)
from stats_field_names_lookup as l
where l.field_name in ('Q001001', 'Q001002', 'Q001005');
Run Code Online (Sandbox Code Playgroud)
这里的想法是,sum(l.field_name)
将替换为相关的实际字段名称,对于WHERE
子句中的每个名称,然后进行评估以提供正确的求和结果值.但是,这会因以下错误而失败:
函数和(字符变化)不存在
因为值有文字/字符.如何将该字符值转换为要正确计算的未加引号的字符串?
这个SQL有效.但是,当然,每个都给出相同的和值field_name
,因为它q001001
在这里是硬编码的.
select l.field_name, …
Run Code Online (Sandbox Code Playgroud) 我想在表中添加一个新列,以记录每个元组(行)的值为null的属性数.如何使用SQL获取数字?
例如,如果元组是这样的:
Name | Age | Sex
-----+-----+-----
Blice| 100 | null
Run Code Online (Sandbox Code Playgroud)
我想更新元组,如下所示:
Name | Age | Sex | nNULL
-----+-----+-----+--------
Blice| 100 | null| 1
Run Code Online (Sandbox Code Playgroud)
另外,因为我正在编写PL/pgSQL函数并且表名是从参数获得的,所以我事先并不知道表的模式.这意味着我需要使用输入表名更新表.有人知道怎么做吗?
我是plpgsql的新手.我正在尝试使用plpgsql中的变量作为表名在plpgsql中运行一个简单的查询.但是变量被解释为表名而不是被解释为变量名的变量的值.
DECLARE
v_table text;
z_table text;
max_id bigint;
BEGIN
FOR v_table IN
SELECT table_name
FROM information_schema.tables
WHERE table_catalog = 'my_database'
AND table_schema = 'public'
AND table_name not like 'z_%'
LOOP
z_table := 'z_' || v_table;
SELECT max(id) from z_table INTO max_id;
DELETE FROM v_table where id > max_id;
END LOOP;
Run Code Online (Sandbox Code Playgroud)
一些背景资料.对于我的数据库中的每个表,我有另一个以"z_"开头的表.例如,对于一个名为"employee"的表,我有一个名为"z_employee"的相同表.z_employee
包含与员工相同的数据集.我在每次测试开始时使用它来恢复employee表.
当我运行此函数时,我收到以下错误:
ERROR: relation "z_table" does not exist
LINE 1: SELECT max(id) from z_table
Run Code Online (Sandbox Code Playgroud)
我的猜测是我不允许z_table
在SQL查询中使用该变量.至少不是我在这里使用它的方式.但我不知道它应该如何完成.
我有以下代码来创建一个函数,web_channel2
如果表不为空,则截断表中的所有行:
create or replace function truncate_if_exists(tablename text)
returns void language plpgsql as $$
begin
select
from information_schema.tables
where table_name = tablename;
if found then
execute format('truncate %I', tablename);
end if;
end $$;
Run Code Online (Sandbox Code Playgroud)
不幸的是我不知道应该如何继续...如何执行该函数?
我不得不求助于ORM不足的原始SQL(使用Django 1.7).问题是大多数查询最终都有80-90%的相似性.在不违反可重用性的情况下,我无法找到构建查询的强大而安全的方法.
字符串连接是唯一的出路,即使用if-else
条件构建无参数查询字符串,然后使用预准备语句安全地包含参数(以避免SQL注入).我想按照一种简单的方法来为我的项目模板化SQL,而不是重新发明一个迷你ORM.
例如,考虑以下查询:
SELECT id, name, team, rank_score
FROM
( SELECT id, name, team
ROW_NUMBER() OVER (PARTITION BY team
ORDER BY count_score DESC) AS rank_score
FROM
(SELECT id, name, team
COUNT(score) AS count_score
FROM people
INNER JOIN scores on (scores.people_id = people.id)
GROUP BY id, name, team
) AS count_table
) AS rank_table
WHERE rank_score < 3
Run Code Online (Sandbox Code Playgroud)
我怎么能够:
a)添加可选WHERE
约束people
或
b)更改INNER JOIN
为LEFT OUTER
或
c)更改COUNT
为SUM
或
d)完全跳过该OVER …
如何SELECT INTO
在Postgres的PL / pgSQL函数内编写动态查询?
假设我有一个名为的变量tb_name
,它填充在的FOR
循环中information_schema.tables
。现在,我有一个名为的变量tc
,它将获取每个表的行数。我想要以下内容:
FOR tb_name in select table_name from information_schema.tables where table_schema='some_schema' and table_name like '%1%'
LOOP
EXECUTE FORMAT('select count(*) into' || tc 'from' || tb_name);
END LOOP
Run Code Online (Sandbox Code Playgroud)
应该是什么数据类型tb_name
,并tc
在这种情况下?
postgresql dynamic-sql plpgsql variable-assignment stored-functions
postgresql ×10
plpgsql ×7
dynamic-sql ×6
sql ×5
count ×1
cursor ×1
null ×1
orm ×1
sanitization ×1
search-path ×1
sql-update ×1
truncate ×1
unpivot ×1