简体   繁体   English

如何在单个 Select 语句中执行动态 SQL 语句?

[英]How to execute a dynamic SQL statement in a single Select statement?

I just wonder how to eval the content of dynamic SQL using one select;我只是想知道如何使用一个 select 来评估动态 SQL 的内容; this is the example.这就是例子。 This is only an example.这只是一个例子。 but I would like dynamically functions, and manage using single selects.但我想要动态函数,并使用单选进行管理。 ( I know that sqls are only for SELECT instead of modify... but In this deep querentee Im becomeing in a crazy developer) (我知道 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';

The original output is:原output为:

SELECT SETVAL('viewitem_id_seq' , (SELECT MAX(Id)+1 FROM viewitem ), true );
SELECT SETVAL('userform_id_seq' , (SELECT MAX(Id)+1 FROM userform ), true );

This is the dynamic sentence: (SELECT MAX(Id)+1 FROM ' || regexp_replace(c.relname, ' [a-zA-Z]+ [a-zA-Z]+(_[a-zA-Z0-9]+)?', '', 'g')这是动态语句: (SELECT MAX(Id)+1 FROM ' || regexp_replace(c.relname, ' [a-zA-Z]+ [a-zA-Z]+(_[a-zA-Z0- 9]+)?', '', 'g')

is an string that generates as output a SQL, how to eval in the same line this statement?是一个生成为 output 和 SQL 的字符串,如何在同一行中评估此语句?

The desired output is:所需的 output 是:

SELECT SETVAL('viewitem_id_seq' , 25, true );
SELECT SETVAL('userform_id_seq' , 85, true );

thanks!谢谢!

If those are serial or identity columns it would be better to use pg_get_serial_sequence() to get the link between a table's column and its sequence.如果这些是serialidentity列,最好使用pg_get_serial_sequence()来获取表的列与其序列之间的链接。

You can actually run dynamic SQL inside a SQL statement by using query_to_xml()您实际上可以使用query_to_xml()在 SQL 语句中运行动态 SQL

I use the following script if I need to synchronize the sequences for serial (or identity ) columns with their actual values:如果我需要将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;

The dynamic part here is the call to query_to_xml()这里的动态部分是对query_to_xml()的调用

First I use format() to properly deal with identifiers.首先,我使用format()来正确处理标识符。 It also makes writing the SQL easier as no concatenation is required.它还使编写 SQL 更容易,因为不需要连接。 So for every table returned by the first CTE, something like this is executed:因此,对于第一个 CTE 返回的每个表,都会执行以下操作:

query_to_xml('select max(id) from public.some_table', true, true, '')

This returns something like:这会返回类似:

<row xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <max>42</max>
</row>

The value is than extracted from the XML value using xpath() and converted to a number which then is used in the final SELECT to actually call setval()该值比使用 xpath() 从 XML 值中提取并转换为一个数字,然后在最终 SELECT 中使用以实际调用setval()

The nesting with multiple CTEs is only used to make each part more readable.具有多个 CTE 的嵌套仅用于使每个部分更具可读性。

The same approach can eg used to find the row count for all tables例如,可以使用相同的方法来查找所有表的行数

Some background on how query_to_xml() works关于query_to_xml()如何工作的一些背景知识

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM