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

T-SQL Error Message 207 When passing values Dynamically

我正在尝试创建一个允许将值传递给它的存储过程,但是,当我尝试使用 Dynamic 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

使用动态字符串时,首先 select 它们,这样您就可以检查生成的语法是否可行。

结果中需要单引号,所以需要的不仅仅是单引号,在代码中:

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');                                                         |
+-------------------------------------------------------------------------------------------------------------------+

NB 你应该使用 convert(char(8),getdate(),112) SQL 无论服务器默认设置如何,服务器都会将 YYYYMMDD 格式识别为日期值。


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

当您连接 SQL 语句时,您也在处理字符串,并且每个部分都必须包含在单引号内。

所以单引号有多种需求

并且;因此,您需要在整个连接过程中使用多个单引号,一些用于帮助形成 SQL 语句,而另一些则位于该语句的内部。

/* get this into @sql */
select 'Y' as col1;

declare @SQL as nvarchar(max)

set @SQL = N'select ''Y'' as col1;'

select @SQL;

+---------------------+
|        @SQL         |
+---------------------+
| select 'Y' as col1; |
+---------------------+

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

如评论中所述,根本不需要这种动态方法。

以下代码将展示直接和动态的方法。试试看:

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;