2

执行此操作时我没有收到任何错误,但是当我真正想要的是它在我的数据库中创建一个名为“dbo.@tablename”的表时,它会创建我在 exec 过程中作为参数传递的值表名。我究竟做错了什么。这是我的更新程序脚本。也许我可以更改,以便它确实将值创建为表名。

这是我到目前为止所拥有的:

ALTER PROCEDURE [dbo].[Load_Negatives]
        -- Add the parameters for the stored procedure here
        @TABLENAME SYSNAME, 
        @AuditPeriodStartDate datetime,
        @AuditPeriodEndDate datetime
    AS
    BEGIN
        SET NOCOUNT ON;
Select 
    Location,
    Customer,
    Transaction_date
    into
        dbo.[@TABLENAME]
     from dbo.CustomerHistory (nolock)
    where
    [Transaction_date] between @AuditPeriodStartDate and @AuditPeriodEndDate

END
4

1 回答 1

7

表名不能参数化。因此,您需要动态构建 SQL 语句,将名称合并到动态脚本中。

为了最大限度地降低 SQL 注入的风险,请使用QUOTENAME带有值的系统函数,@TABLENAME并在动态查询中引入参数化以传递存储过程的其他两个参数:

ALTER PROCEDURE [dbo].[Load_Negatives]
    @TABLENAME SYSNAME, 
    @AuditPeriodStartDate datetime,
    @AuditPeriodEndDate datetime
AS
BEGIN

SET NOCOUNT ON;

DECLARE @sql nvarchar(max);
SET @sql = N'Select 
    Location,
    Customer,
    Transaction_date
    into
        dbo.' + QUOTENAME(@TABLENAME) + N'
     from dbo.CustomerHistory (nolock)
    where
    [Transaction_date] between @AuditPeriodStartDate and @AuditPeriodEndDate'
;
EXECUTE sp_executesql
    @sql,
    N'@AuditPeriodStartDate datetime, @AuditPeriodEndDate datetime',
    @AuditPeriodStartDate, @AuditPeriodEndDate
;

END

基本上,动态查询看起来与您当前的查询几乎完全相同。唯一的区别是表名是作为QUOTENAME(@TABLENAME). 动态查询的datetime参数恰好与存储过程的相应参数具有相同的名称,但这不是强制性的。

EXECUTE sp_executesql语句将datetime参数传递给动态查询,然后执行它。

另一个注意事项是关于您使用带有值的BETWEEN谓词。datetime如果Transaction_date包含具有非零时间部分的时间戳,最好以这种形式指定范围:

 [Transaction_date] >= @AuditPeriodStartDate
 and
 [Transaction_date] < @AuditPeriodEndDate

这样您就可以确定结果将仅包含相关值。更多信息可以在这篇博客文章中找到:

于 2013-10-31T00:16:16.463 回答