如何在单个 Select 语句中执行动态 SQL 语句?
How to execute a dynamic SQL statement in a single Select statement?
我只是想知道如何使用 select 评估动态 SQL 的内容;这是例子。这只是一个例子。但我想要动态功能,并使用单个 selects 进行管理。 (我知道 sqls 仅用于 SELECT 而不是修改...但在这个深度查询中,我正在成为一个疯狂的开发人员)
SELECT 'SELECT SETVAL(' || chr(39) || c.relname || chr(39)|| ' ,
(SELECT MAX(Id)+1 FROM ' || regexp_replace(c.relname, '_[a-zA-Z]+_[a-zA-Z]+(_[a-zA-Z0-9]+)?', '', 'g') ||' ), true );'
FROM pg_class c WHERE c.relkind = 'S';
原输出为:
SELECT SETVAL('viewitem_id_seq' , (SELECT MAX(Id)+1 FROM viewitem ), true );
SELECT SETVAL('userform_id_seq' , (SELECT MAX(Id)+1 FROM userform ), true );
这是动态语句:
(SELECT MAX(Id)+1 FROM ' || regexp_replace(c.relname, '[a-zA-Z]+[a- zA-Z]+(_[a-zA-Z0-9]+)?', '', 'g')
是一个字符串,生成一个SQL作为输出,如何在同一行eval这个语句?
期望的输出是:
SELECT SETVAL('viewitem_id_seq' , 25, true );
SELECT SETVAL('userform_id_seq' , 85, true );
谢谢!
如果这些是 serial
或 identity
列,最好使用 pg_get_serial_sequence()
在 table 的列和它的顺序。
您实际上可以 运行 在 SQL 语句中使用 query_to_xml()
动态 SQL
如果我需要将 serial
(或 identity
)列的序列与其实际值同步,我会使用以下脚本:
with sequences as (
-- this query is only to identify all sequences that belong to a column
-- it's essentially similar to your select * from pg_class where reltype = 'S'
-- but returns the sequence name, table and column name to which the
-- sequence belongs
select *
from (
select table_schema,
table_name,
column_name,
pg_get_serial_sequence(format('%I.%I', table_schema, table_name), column_name) as col_sequence
from information_schema.columns
where table_schema not in ('pg_catalog', 'information_schema')
) t
where col_sequence is not null
), maxvals as (
select table_schema, table_name, column_name, col_sequence,
--
-- this is the "magic" that runs the SELECT MAX() query
--
(xpath('/row/max/text()',
query_to_xml(format('select max(%I) from %I.%I', column_name, table_schema, table_name), true, true, ''))
)[1]::text::bigint as max_val
from sequences
)
select table_schema,
table_name,
column_name,
col_sequence,
coalesce(max_val, 0) as max_val,
setval(col_sequence, coalesce(max_val, 1)) --<< this uses the value from the dynamic query
from maxvals;
这里的动态部分是对query_to_xml()
的调用
首先我使用 format()
来正确处理标识符。它还使编写 SQL 更容易,因为不需要连接。因此,对于第一个 CTE 返回的每个 table,都会执行如下操作:
query_to_xml('select max(id) from public.some_table', true, true, '')
这 returns 类似于:
<row xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<max>42</max>
</row>
然后使用 xpath() 从 XML 值中提取该值并转换为数字,然后在最终 SELECT 中实际调用 setval()
嵌套多个CTE只是为了让每个部分更具可读性。
同样的方法可以,例如习惯了find the row count for all tables
关于 query_to_xml()
工作原理的一些
我只是想知道如何使用 select 评估动态 SQL 的内容;这是例子。这只是一个例子。但我想要动态功能,并使用单个 selects 进行管理。 (我知道 sqls 仅用于 SELECT 而不是修改...但在这个深度查询中,我正在成为一个疯狂的开发人员)
SELECT 'SELECT SETVAL(' || chr(39) || c.relname || chr(39)|| ' ,
(SELECT MAX(Id)+1 FROM ' || regexp_replace(c.relname, '_[a-zA-Z]+_[a-zA-Z]+(_[a-zA-Z0-9]+)?', '', 'g') ||' ), true );'
FROM pg_class c WHERE c.relkind = 'S';
原输出为:
SELECT SETVAL('viewitem_id_seq' , (SELECT MAX(Id)+1 FROM viewitem ), true );
SELECT SETVAL('userform_id_seq' , (SELECT MAX(Id)+1 FROM userform ), true );
这是动态语句: (SELECT MAX(Id)+1 FROM ' || regexp_replace(c.relname, '[a-zA-Z]+[a- zA-Z]+(_[a-zA-Z0-9]+)?', '', 'g')
是一个字符串,生成一个SQL作为输出,如何在同一行eval这个语句?
期望的输出是:
SELECT SETVAL('viewitem_id_seq' , 25, true );
SELECT SETVAL('userform_id_seq' , 85, true );
谢谢!
如果这些是 serial
或 identity
列,最好使用 pg_get_serial_sequence()
在 table 的列和它的顺序。
您实际上可以 运行 在 SQL 语句中使用 query_to_xml()
如果我需要将 serial
(或 identity
)列的序列与其实际值同步,我会使用以下脚本:
with sequences as (
-- this query is only to identify all sequences that belong to a column
-- it's essentially similar to your select * from pg_class where reltype = 'S'
-- but returns the sequence name, table and column name to which the
-- sequence belongs
select *
from (
select table_schema,
table_name,
column_name,
pg_get_serial_sequence(format('%I.%I', table_schema, table_name), column_name) as col_sequence
from information_schema.columns
where table_schema not in ('pg_catalog', 'information_schema')
) t
where col_sequence is not null
), maxvals as (
select table_schema, table_name, column_name, col_sequence,
--
-- this is the "magic" that runs the SELECT MAX() query
--
(xpath('/row/max/text()',
query_to_xml(format('select max(%I) from %I.%I', column_name, table_schema, table_name), true, true, ''))
)[1]::text::bigint as max_val
from sequences
)
select table_schema,
table_name,
column_name,
col_sequence,
coalesce(max_val, 0) as max_val,
setval(col_sequence, coalesce(max_val, 1)) --<< this uses the value from the dynamic query
from maxvals;
这里的动态部分是对query_to_xml()
首先我使用 format()
来正确处理标识符。它还使编写 SQL 更容易,因为不需要连接。因此,对于第一个 CTE 返回的每个 table,都会执行如下操作:
query_to_xml('select max(id) from public.some_table', true, true, '')
这 returns 类似于:
<row xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<max>42</max>
</row>
然后使用 xpath() 从 XML 值中提取该值并转换为数字,然后在最终 SELECT 中实际调用 setval()
嵌套多个CTE只是为了让每个部分更具可读性。
同样的方法可以,例如习惯了find the row count for all tables
关于 query_to_xml()
工作原理的一些