标签: dynamic-sql

“错误:“EXECUTE .. USING ..;”中没有参数 $1” plpgsql 中的语句

我有一个 plpgsql 函数来使用 PostgreSQL 中的表继承创建子表,如下所示:

CREATE TABLE parent_table (
  value integer,
  end_time timestamp without time zone
);

CREATE OR REPLACE FUNCTION mk_child(_year INTEGER, _month INTEGER)
  RETURNS text AS $$
DECLARE
  tname varchar;
  start_date date;
  end_date date;
  next_month varchar := (_month + 1)::text;
  next_year varchar := (_year + 1)::text;
BEGIN
  tname := 'child_y' || substring(_year::text from 3 for 2)
           || 'm' || lpad(_month::text, 2, '0');
  start_date := DATE (_year::text || '-' || _month::text || '-01');
  IF ( _month = 12 ) …
Run Code Online (Sandbox Code Playgroud)

postgresql dynamic-sql ddl plpgsql postgresql-9.4

5
推荐指数
1
解决办法
1万
查看次数

如何使用变量的值设置列 DEFAULT

在设置使用随机 UUID 作为主键的数据库的脚本中,我有:

CREATE TABLE alpha (id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), value INT);
CREATE TABLE beta (aref UUID REFERENCES alpha (id));

INSERT INTO alpha (value) VALUES (42);
Run Code Online (Sandbox Code Playgroud)

然后通过外键,让“alpha”中的记录成为插入“beta”表的默认目标:

DO $$
    DECLARE l_id UUID;
    BEGIN
        SELECT alpha.id FROM alpha INTO l_id;
        ALTER TABLE beta ALTER COLUMN aref SET DEFAULT l_id;
    END;
$$ LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)
ERROR:  column "l_id" does not exist
CONTEXT:  SQL statement "ALTER TABLE beta ALTER COLUMN aref SET DEFAULT l_id"
PL/pgSQL function inline_code_block line 1 at SQL statement …
Run Code Online (Sandbox Code Playgroud)

postgresql dynamic-sql default-value alter-table plpgsql

5
推荐指数
1
解决办法
4661
查看次数

如何使用 format() 函数引用限定表名?

format我在使用下面示例中的函数正确引用表名时遇到一些问题。

CREATE OR REPLACE FUNCTION copy_table(_source_tbl regclass, _target_tbl text)
 RETURNS bool AS $func$
DECLARE query_str text; 
BEGIN
  query_str = format($fmt$ DROP TABLE IF EXISTS %1$I; CREATE TABLE %1$I AS (TABLE %s); $fmt$, _target_tbl, _source_tbl);
  EXECUTE query_str;
  RAISE NOTICE '%', query_str;
 RETURN True;
END $func$ LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)

我的困境是我想引用输入表名称_target_tbl作为标识符(以避免 SQL 注入)。但是,给定完整的表名称ex.test1,这会导致架构部分ex.被视为表名称的一部分,并public."ex.test1"在默认public.架构中创建表,如下所示。

我应该如何在此处正确引用/格式化标识符?

=> SELECT copy_table('ex.test', 'ex.test1');
NOTICE:  table "ex.test1" does not exist, skipping
NOTICE:   DROP TABLE IF EXISTS "ex.test1"; CREATE TABLE …
Run Code Online (Sandbox Code Playgroud)

postgresql dynamic-sql plpgsql postgresql-10

5
推荐指数
1
解决办法
3448
查看次数

动态定义一个RETURN表(列类型,名称)用于后续循环

我想对ST_Intersection(clipper_geom, clipped_geom)来自表的行数执行。

https://postgis.net/docs/ST_Intersection.html

https://postgis.net/docs/ST_Intersects.html

POSTGIS 交集本身不支持处理多个几何图形,这与ST_Intersects()我必须设计一个函数(返回一个表)来选择与我的clipper_geomusing相交的行ST_Intersects()、循环遍历结果集并计算与 的每个交集有关ST_Intersection()。字段geomclipped_geom_wkt是记录剪裁几何体的字段。

该功能有效,但我需要为每个要生成剪辑的表使用不同的功能。我想动态读取输入表(列名称和类型)并在RETURN语句中定义两者。

所有字段名称和类型都相同,只是geom更新和clipped_geom_wkt添加。

我尝试搜索 Stack Overflow,找到了有关如何创建动态表结构的示例,但没有一个LOOP对第一个结果执行后续操作,其中列名必须匹配才能插入/更新新数据。

这是我到目前为止所提出的,但我不确定如何执行该LOOP部分、添加clipped_geom_wkt字段和更新geom字段。一些回复建议RETURNS TABLE (...)如果添加更多字段SETOF...

/sf/ask/1247503771/

但似乎动态生成的列仅支持RETURNS SETOF ...

/sf/ask/821817951/#11751557

/sf/ask/602362211/#8611675

CREATE OR REPLACE FUNCTION clip_palin_polygon_complete(clipped_table text,clipper_geom text, age_sequence VARCHAR)
RETURNS TABLE (rec clipped_table, clipped_geom_wkt text)) AS $$ --not sure if this is the right way to …
Run Code Online (Sandbox Code Playgroud)

postgresql dynamic-sql plpgsql postgis

5
推荐指数
1
解决办法
1万
查看次数

sp_executesql 不使用参数

我遇到了一个奇怪的动态 sql 问题,我认为这是某种格式问题,在过去的几个小时里我一直在为此抓狂。我非常感谢我能得到的任何帮助。

对于一些背景信息,此存储过程的目的是清理我们的集中式 (hq) 数据库中的数据,该数据库应该拥有我们所有商店的所有记录的完整副本。如果重要的话,我们正在运行 Microsoft Dynamics RMS (2.0.2022) 和 SQL 2014 Standard(对于总部,商店使用 Express)。

最初我打算将 sql 语句放在参数中并使用 exec 命令,但是虽然我不经常使用它,但我认为 sp_executesql 看起来更干净,并且更容易将查询重用为模板并进行更改他们。现在我只有一些选择的脚本,但是一旦它们完成,我将创建一个额外的存储过程来插入、删除和更新记录。

执行 sql 语句有效,但出于某种原因,我无法让 sp_executesql 使用存储过程中的参数。无论我将参数更改为什么,包括在存储过程中使用静态值,它都只会输出参数名称。所以无论:

@LS = @LinkedServer
Run Code Online (Sandbox Code Playgroud)

或者

@LS = 'StaticLinkedServerName'
Run Code Online (Sandbox Code Playgroud)

它返回的错误信息是:

在 sys.servers 中找不到服务器“@LS”。验证是否指定了正确的服务器名称。如有必要,执行存储过程 sp_addlinkedserver 将服务器添加到 sys.servers。

无效的解决方案

CREATE PROCEDURE [dbo].[usp_bn_ShowStoreHQSync]  
(
      @StoreCode        NVARCHAR(10)
     ,@LinkedServer     NVARCHAR(50)    
     ,@StoreDB          NVARCHAR(40)
)
AS          
BEGIN   
    BEGIN TRANSACTION
        BEGIN TRY
            IF @StoreCode IS NULL
                RAISERROR('@StoreCode Cannot Be NULL',15,1)
            ELSE IF @StoreCode NOT IN (SELECT StoreCode FROM [HQDB].[dbo].[Store])
                RAISERROR('@StoreCode Not In DB',15,1) …
Run Code Online (Sandbox Code Playgroud)

sql-server dynamic-sql t-sql

5
推荐指数
1
解决办法
1426
查看次数

遵守 DRY 原则是否证明动态 SQL 是合理的?

假设我有两个经常针对我的数据库运行的查询:

SELECT 
  UserID,
  UserName,
  UserGender
FROM Users
WHERE UserID = @User

SELECT 
  UserID,
  UserName,
  UserGender
FROM Users
WHERE UserName LIKE @Name + '%
Run Code Online (Sandbox Code Playgroud)

它们应该在两个单独的存储过程中,还是只是一个使用 sp_executesql 动态创建语句的存储过程?

如果它们在两个存储过程中,那么如果我想在 SELECT 语句中添加或删除列,我将需要修改这两个过程。如果我使用动态 SQL,那么大概我会牺牲少量的性能。

在这种情况下,使用动态 SQL 的可维护性和遵守 DRY 原则(不要重复自己)会优先于存储过程的性能增益吗?

best-practices stored-procedures dynamic-sql

4
推荐指数
2
解决办法
751
查看次数

按参数在百分比和行之间切换 TOP 子句

对于一份报告,我正在查询用户假设必须根据百分比选择 TOP 值或固定行数。

我有两个想法

根据传递的参数调用两个不同的子存储过程。

if @param ='percent'
begin
      exec sp_data_TOP_by_Percent
end
if @param ='perRow'
begin
    exec sp_data_TOP_by_PerRow
end
Run Code Online (Sandbox Code Playgroud)

另一个想法是使动态 TSQL 查询像这样

declare @command nchar(max)

select @command = 'select top(10) '
                   + case @param 
                              when 'percent' then percent 
                              else ' '
                     end
                   + ' * '
                   + 'from table 
                        order by 1';
exec sp_executesql @command
Run Code Online (Sandbox Code Playgroud)

像这样的事情有第三种解决方案吗?
什么是更好的方法?第一个避免动态 TSQL,但在两个地方更难维护代码。我使用 MSSQL2005 作为数据库。

sql-server-2005 sql-server dynamic-sql t-sql parameter

4
推荐指数
1
解决办法
433
查看次数

动态支点:每月销售额总和

我的表是这样的:

Sitecode    Month  Amount
--------    -----  ------
XX          Jan     1000
XX          Jan     3000
XX          Apr     3000
XX          Apr     1000
Run Code Online (Sandbox Code Playgroud)

我想要的是,显示这样的结果:

Sitecode    MonthJAN   MonthAPR
--------    --------   --------
XX          4000       4000
Run Code Online (Sandbox Code Playgroud)

sql-server pivot dynamic-sql

4
推荐指数
2
解决办法
7万
查看次数

使用带有 psql 变量作为参数的表达式创建序列

我已经用 Postgres 玩了一个星期左右,我正在看看是否可以使用表达式设置序列的最小值/最大值。具体目标是为服务器之间的不相交范围自动创建脚本,以避免多主设置中的密钥冲突。

例如,使用 psql:

CREATE SEQUENCE key_seq MINVALUE (:servernum * :stride)
                        MAXVALUE ((:servernum + 1) * :stride - 1);
Run Code Online (Sandbox Code Playgroud)

这给了我一个语法错误。变量是逐字内插的,不进行计算。

另一种方法是根据表达式的输出设置变量:

\set minvalue (:servernum * :stride)
Run Code Online (Sandbox Code Playgroud)

但该\set语句不计算表达式。

postgresql psql sequence dynamic-sql ddl

4
推荐指数
1
解决办法
2169
查看次数

exec(sql) 的安全替代方案

我发现exec(sql)代码中隐藏了一些语句。它们存在是有充分理由的,因为这些语句不能直接编写,但它们是一个明显的攻击媒介。

有没有安全的替代品exec(some sql)?将正确参数化的东西,包括语句中的表名?

security sql-server sql-injection dynamic-sql t-sql

4
推荐指数
1
解决办法
2705
查看次数