在存储过程中为字符串 SQL 查询中的变量赋值

问题描述 投票:0回答:1

我有一个现有的存储过程,它将源表名称和目标表名称作为 Varchar 参数,并执行一些复杂的逻辑。我的要求是使用源表的column1 并使用该值构建串联输出。例如,

表A

Column1
--------
090912
899823
687678

我仅采用前 2 位数字并将其连接起来以创建类似“09,89,68”的输出。这用于其他计算。

@AllCode
作为一个
varchar(max)
变量,我添加了下面的 select 语句,如果直接给出表名,它可以正常工作。现在,我尝试用 varchar 的输入参数替换 TableA。如果我使用变量,那么我应该使用 Exec 语句。这就是我努力包含 @allCode 变量赋值的地方。

is 行与实际表名称配合良好:

select @AllCode = @AllCode + ' ' + Code 
from 
    (select distinct left(Column1,2) as Code 
     from TableA 
     where TableA.Processedflag is null) tmp

print @AllCode --> 09,89,68

我写了下面的代码。从上面的行分配子查询并将其添加到

@SqlQuery
变量。我不知道如何扩展此查询并使用 Exec 包含
@AllCode
变量赋值。

alter procedure temp.spSample
    @SrcTbl varchar(100),
    @TgtTbl varchar(100)
as
begin
    declare @AllCode varchar(500);
    declare @SqlQuery varchar(max);

    set @SqlQuery = 'select distinct left(Column1,2) as Code from ' + @SrcTbl + ' where ' + @SrcTbl  +'.ProcessedFlag is null';

    exec(@SqlQuery);
end

如何在没有表变量的情况下实现上述功能?我无法使用表变量,因为它需要在存储过程之外创建。

我尝试使用表变量并将值存储在表变量中。但是,在同一个存储过程中,我无法使用 CREATE 表变量并在同一过程中使用表变量。我遇到了找不到表的问题。如果表是在外部创建的,它会工作得很好,但由于维护问题,我不想在外部创建它。

有什么建议吗,如何获得如上例中所述的串联值

@allCode
?没有表变量可以完成吗?

sql sql-server stored-procedures
1个回答
0
投票

你的问题并不完全清楚,我很确定整个问题有更好的方法,但你可以尝试这个:

一般提示:

  • 最好使用
    CONCAT
    ,然后使用
    +
    。这对于各种类型和 NULL 效果更好。
  • 请勿使用
    SELECT @var = @var + ...
    进行字符串聚合。有一些奇怪的副作用。
  • 使用
    QUOTENAME()
    。这有助于防止 SQL 注入。

--创建测试场景

DROP TABLE IF EXISTS dummyTbl;
GO
CREATE TABLE dummyTbl(TheColumn VARCHAR(10), ProcessedFlag BIT);
GO
INSERT INTO dummyTbl VALUES ('090912',1)
                           ,('899823',0)
                           ,('123456',1)
                           ,('654321',0)
                           ,('687678',0);
GO

--这是聚合字符串值的最佳方式

DECLARE @allCodes VARCHAR(MAX)=
(
    SELECT STRING_AGG(LEFT(t.TheColumn,2),',')
    FROM dummyTbl t
    WHERE t.ProcessedFlag=0
);
PRINT @allCodes;
GO

--在两者之间使用 JSON 来允许变量列名称(但不适用于表名称)的技巧

DECLARE @columnName VARCHAR(100)='TheColumn';
DECLARE @allCodes VARCHAR(MAX)=
(
    SELECT STRING_AGG(LEFT(TheValue.OfColumn,2),',')
    FROM dummyTbl t
    CROSS APPLY(SELECT JSON_VALUE((SELECT t.* FOR JSON PATH, WITHOUT_ARRAY_WRAPPER),CONCAT('$.',@columnName))) TheValue(OfColumn)
    WHERE t.ProcessedFlag=0
);
PRINT @allCodes;
GO

--从变量表和列中检索值的完全动态方法
--重要提示:在系统名周围使用

QUOTENAME()
。这有助于避免 SQL 注入。

DECLARE @tableName VARCHAR(100)='dummyTbl';
DECLARE @columnName VARCHAR(100)='TheColumn';
DECLARE @allCodes VARCHAR(MAX);

DECLARE @cmd NVARCHAR(MAX)=CONCAT
(
N'SELECT @allCodes=STRING_AGG(LEFT(t.',QUOTENAME(@columnName),',2),'','')
  FROM ',QUOTENAME(@tableName),' t
  WHERE t.ProcessedFlag=0;'
);
--This will execute the dynamic statement and *output* the assigned variable
EXEC sp_executesql @cmd, N'@allCodes VARCHAR(MAX) OUT', @allCodes OUTPUT;
PRINT @allCodes;
GO

--清洁

DROP TABLE IF EXISTS dummyTbl;
GO

结果,您将看到三倍相同的打印值链。

© www.soinside.com 2019 - 2024. All rights reserved.