T-SQL错误消息207动态传递值时

时间:2018-11-08 23:54:17

标签: sql-server tsql stored-procedures dynamic-sql

我试图创建一个允许将值传递给它的存储过程,但是,当我尝试使用动态T-SQL时,出现了MSG 207错误

由于以下站点,我知道错误消息应该表明列名在我的语句中拼写错误:

https://www.tsql.info/error/msg-207-level-16-invalid-column-name.php

但是,这没有意义,因为以下硬编码语句可以正常工作。

INSERT INTO [dbo].[tDriversLicense] (DriversLicensePrefix,    DriversLicenseSuffix, DateAdded, DriversLicenseNumber)
    VALUES ('shockc', '11653798', GETDATE(), 'GAD4859');

ALTER PROCEDURE [dbo].[spAddDriversLicense]
    -- Add the parameters for the stored procedure here
    @DriversLicensePrefix NCHAR(8),
    @DriversLicenseSuffix NCHAR(10)
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

            DECLARE @sqlInsertDriversLicense NVARCHAR(MAX)
            SET @sqlInsertDriversLicense = 'INSERT INTO [dbo].[tDriversLicense] (DriversLicensePrefix, DriversLicenseSuffix, DateAdded, DriversLicenseNumber)
                VALUES (' + @DriversLicensePrefix + ', ' + @DriversLicenseSuffix + ', GETDATE(), GPC4859);'

            EXECUTE sp_executesql @sqlInsertDriversLicense

END

我已经花了几个小时来讨论这段代码,而我对为什么两个INSERT语句之间有什么区别感到非常困惑。传递的值相同,但是当我尝试动态传递它们时会引发错误。这怎么引发错误?

我已使用此视频中的一些代码来尝试学习如何动态传递标量值,并在其他存储过程中运气不错。

https://www.youtube.com/watch?v=RHHKG65WEoU

2 个答案:

答案 0 :(得分:2)

使用动态字符串时,请首先选择它们,以便您可以检查生成的语法是否可用。

结果中需要单引号,因此代码中需要的不仅仅是单引号。

declare @DriversLicensePrefix nchar(8) = 'A2345678'
declare @DriversLicenseSuffix nchar(10) = 'abcdefghij'

DECLARE @sqlInsertDriversLicense nvarchar(max)
SET @sqlInsertDriversLicense = 'INSERT INTO [dbo].[tDriversLicense] (DriversLicensePrefix, DriversLicenseSuffix, DateAdded, DriversLicenseNumber)
                VALUES (N''' + @DriversLicensePrefix + ''', N''' + @DriversLicenseSuffix + ''', ''' + convert(char(8),GETDATE(),112) + ''', ''GPC4859'');'

select @sqlInsertDriversLicense

+-------------------------------------------------------------------------------------------------------------------+
|                                                      result:                                                      |
+-------------------------------------------------------------------------------------------------------------------+
| INSERT INTO [dbo].[tDriversLicense] (DriversLicensePrefix, DriversLicenseSuffix, DateAdded, DriversLicenseNumber) |
| VALUES (N'A2345678', N'abcdefghij', '20181109', 'GPC4859');                                                         |
+-------------------------------------------------------------------------------------------------------------------+

注意事项:无论服务器的默认设置如何,SQL Server都会将YYYYMMDD格式识别为日期值。


上面看到的结果演示了插入语句必须是什么,请注意它包含几个单引号。

在连接SQL语句时,您还需要处理字符串,并且字符串的每个部分都必须包含在单引号中。

因此,单引号有多种需求。

然后;因此,您需要在整个串联过程中使用多个单引号,其中一些可以帮助形成SQL语句,而另一些可以将其插入该语句中。

convert(char(8),getdate(),112)

在较大的查询中,已将两个变量定义为NCHAR(8)或(10),因为您已将它们定义为 N char,然后在将数据插入到其中的变量时,应在输入的前面加上 N

答案 1 :(得分:2)

已经在评论中发布,根本不需要这种动态方法。

以下代码将展示一种简单而动态的方法。试试看:

USE master;
GO
CREATE DATABASE testDB;
GO
USE testDB;
GO
CREATE TABLE TestTable(SomeContent VARCHAR(100),SomeDate DATETIME,SomeFixString VARCHAR(100));
GO

-此过程将直接使用参数。不需要任何动态SQL:

CREATE PROCEDURE TestStraight(@content VARCHAR(100))
AS
BEGIN
    INSERT INTO TestTable(SomeContent,SomeDate,SomeFixString)
    VALUES(@content,GETDATE(),'Proc Straight');
END
GO

-此过程将使用真实参数。您应该切勿在字符串连接中使用参数。有一天您可能会遇到bobby tables ...

CREATE PROCEDURE TestDynamic(@content VARCHAR(100))
AS
BEGIN
    DECLARE @cmd NVARCHAR(MAX)=
    N'INSERT INTO TestTable(SomeContent,SomeDate,SomeFixString)
      VALUES(@DynamicContent,GETDATE(),''Proc Dynamic'');'
    EXEC sp_executesql @cmd,N'@DynamicContent VARCHAR(100)',@DynamicContent=@content;
END
GO

-测试

EXEC TestStraight 'yeah!';
EXEC TestDynamic 'oh yeah!';
SELECT * FROM TestTable;
GO

-清理

USE master;
GO
--careful with real data!
--DROP DATABASE testDB;