插入带有唯一标识符的行

Insert row with uniqueidentifier

这是创建数据库的存储过程的片段。我们有一个带有 uniqueidentifier PK 的 table。我正在尝试插入一个带有空 guid 的行作为 PK:

DECLARE @MailingListId uniqueidentifier
SET @MailingListId = (SELECT cast('00000000-0000-0000-0000-000000000000' AS uniqueidentifier))
DECLARE @MailingListName  varchar(15)
SET @MailingListName = 'General'

SET @str = ('INSERT [' + @db_name + '].[dbo].[MailingLists] ([MailingListId], [MailingListName], [Selected]) 
VALUES (' + @MailingListId + ', ''' + @MailingListName + ''', 0)')
exec (@str);

错误信息是

Msg 156, Level 15, State 1, Line 1198
Incorrect syntax near the keyword 'VALUES'.
Msg 105, Level 15, State 1, Line 1198
Unclosed quotation mark after the character string ')

看不出 VALUES 子句有什么问题,但我猜它与最终报价有关,尽管最终报价是结束报价而不是开始报价。也许这是我将空 guid 分配给 @MailingListId 的方式?应该引用 @MailingListId 吗?

您通过使用 PRINT 语句打印出来调试动态 SQL - 然后您可以调试静态 SQL。

您发布的 SQL 实际上不起作用,它给出了一个错误:

The data types varchar and uniqueidentifier are incompatible in the add operator.

因为您正试图将 @MailingListId 连接到您的动态 SQL 字符串中。鉴于您不妨从一开始就将其设为字符串。

并且在插入 uniqueidentifier 时,您需要引用它,您正在这样做。

DECLARE @db_name VARCHAR(32) = 'MyDatabase', @str NVARCHAR(MAX);

-- No point declaring as uniqueidentifier when you then have to convert back to a string to concatenate below
DECLARE @MailingListId VARCHAR(38) = '00000000-0000-0000-0000-000000000000';
DECLARE @MailingListName VARCHAR(15) = 'General';

SET @str = 'INSERT ' + QUOTENAME(@db_name) + '.[dbo].[MailingLists] ([MailingListId], [MailingListName], [Selected]) 
VALUES (''' + @MailingListId + ''', ''' + @MailingListName + ''', 0)';
--EXEC (@str);
PRINT (@str);

注意使用 QUOTENAME 来防止 SQL 注入。

给出以下有效的 SQL:

INSERT [MyDatabase].[dbo].[MailingLists] ([MailingListId], [MailingListName], [Selected]) 
    VALUES ('00000000-0000-0000-0000-000000000000', 'General', 0);

毕竟你应该按照 Charlieface 的建议去做。但我会把它留在这里,因为你可能仍然会从中学到一些东西。

您应该使用 QUOTENAME 作为数据库名称,并通过 sp_executesql 使用适当的参数。您还可以将空 guid 缩短为 CAST(0x0 AS uniqueidentifier)

DECLARE @MailingListId uniqueidentifier = cast(0x0 AS uniqueidentifier);
DECLARE @MailingListName varchar(15) = 'General';

DECLARE @str nvarchar(max) =
N'INSERT ' + QUOTENAME(@db_name) + N'.[dbo].[MailingLists] ([MailingListId], [MailingListName], [Selected]) 
VALUES (@MailingListId,@MailingListName, 0);';

PRINT @str;  -- for debugging
exec sp_executesql
    @str,
    N'@MailingListId uniqueidentifier, @MailingListName varchar(15)',
    @MailingListId = @MailingListId, @MailingListName = @MailingListName;