我试图创建一个允许将值传递给它的存储过程,但是,当我尝试使用动态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语句之间有什么区别感到非常困惑。传递的值相同,但是当我尝试动态传递它们时会引发错误。这怎么引发错误?
我已使用此视频中的一些代码来尝试学习如何动态传递标量值,并在其他存储过程中运气不错。
答案 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;