在哪里放单引号?

Rau*_*DBA 0 sql-server dynamic-sql t-sql sql-server-2014 quoted-identifier

我正在尝试执行以下语句,该语句创建一个名为 service2019 的数据库:

DECLARE @dbname VARCHAR(50);
SET @dbname = 'service' + CAST(YEAR(GETDATE()) AS VARCHAR(4));


EXEC (
'CREATE DATABASE ' + @dbname  + ' ON  PRIMARY 
( NAME =' + '' + @dbname +'' + ', FILENAME = ''C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQL2014TEST\MSSQL\DATA\''' + '''' + @dbname + '''' + '''.mdf'''  + ', SIZE = 10MB , MAXSIZE = UNLIMITED, FILEGROWTH = 100KB )
 LOG ON 
( NAME =' + '' + @dbname + '_log' + ', FILENAME = ''C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQL2014TEST\MSSQL\DATA\''' + '''' + @dbname + ''''+'''.ldf''' + ', SIZE = 10MB , MAXSIZE = 2048GB , FILEGROWTH = 100KB )'
)
Run Code Online (Sandbox Code Playgroud)

我得到了正确的数据库名称和逻辑名称。问题是我得到了错误的物理名称:

'service2019'.mdf

'service2019'.ldf

有人可以向我解释这些报价实际上是如何工作的吗?有一些部分很清楚,但有时找出这些引号的位置是一个挑战。

Joh*_*ner 6

在开发动态 SQL 时,我建议您从大量使用PRINT命令开始努力,而不是EXEC因为动态 SQL 可能(并且经常会)出错。如果您最终拥有语法正确但逻辑上错误的代码,打印出您的语句而不是实际运行它会帮助您避免一些问题。

在这种特定情况下,我添加了一个新参数,@DSQL VARCHAR(MAX)使用命令设置该变量,并将其打印出来,如下所示:

DECLARE @dbname VARCHAR(50), @DSQL VARCHAR(MAX);
SET @dbname = 'service' + CAST(YEAR(GETDATE()) AS VARCHAR(4));


SET @DSQL = 'CREATE DATABASE ' + @dbname  + ' ON  PRIMARY 
( NAME =' + '' + @dbname +'' + ', FILENAME = ''C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQL2014TEST\MSSQL\DATA\''' + '''' + @dbname + '''' + '''.mdf'''  + ', SIZE = 10MB , MAXSIZE = UNLIMITED, FILEGROWTH = 100KB )
 LOG ON 
( NAME =' + '' + @dbname + '_log' + ', FILENAME = ''C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQL2014TEST\MSSQL\DATA\''' + '''' + @dbname + ''''+'''.ldf''' + ', SIZE = 10MB , MAXSIZE = 2048GB , FILEGROWTH = 100KB )'


PRINT @DSQL
Run Code Online (Sandbox Code Playgroud)

输出以下内容:

CREATE DATABASE service2019 ON  PRIMARY 
( NAME =service2019, FILENAME = 'C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQL2014TEST\MSSQL\DATA\''service2019''.mdf', SIZE = 10MB , MAXSIZE = UNLIMITED, FILEGROWTH = 100KB )
 LOG ON 
( NAME =service2019_log, FILENAME = 'C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQL2014TEST\MSSQL\DATA\''service2019''.ldf', SIZE = 10MB , MAXSIZE = 2048GB , FILEGROWTH = 100KB )
Run Code Online (Sandbox Code Playgroud)

如您所见,您service2019的 mdf 和 ldf 文件路径中有太多引号。经过进一步调查,看起来您的字符串连接数量也多于必要。我建议您做的是将连接(即+)限制在您在变量和静态字符串之间转换的时间。我也是格式化我的 DSQL 的粉丝,所以我还包括一个回车/换行(即\r\n)和制表符(即\t)变量,所以你的输出看起来更干净一些。删除不必要的连接,包括格式,并清理引号让我得到以下信息:

DECLARE @dbname VARCHAR(50), @DSQL VARCHAR(MAX), @CRLF CHAR(2), @TAB CHAR(1);
SET @dbname = 'service' + CAST(YEAR(GETDATE()) AS VARCHAR(4));
SET @CRLF = CHAR(13) + CHAR(10)
SET @TAB = CHAR(9)


SET @DSQL = 'CREATE DATABASE ' + @dbname  + ' ON  PRIMARY 
( NAME = ' + @dbname + ', FILENAME = ''C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQL2014TEST\MSSQL\DATA\' + @dbname + '.mdf'' , SIZE = 10MB , MAXSIZE = UNLIMITED, FILEGROWTH = 100KB )' 
+ @CRLF + @TAB + 'LOG ON' 
+ @CRLF + '( NAME = ' + @dbname + '_log' + ', FILENAME = ''C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQL2014TEST\MSSQL\DATA\' + @dbname + '.ldf'' , SIZE = 10MB , MAXSIZE = 2048GB , FILEGROWTH = 100KB )'


PRINT @DSQL
--EXEC(@DSQL)   /* <--- Uncomment out if you want to run this */
Run Code Online (Sandbox Code Playgroud)

有关更多格式化建议、DSQL 附带陷阱的讨论以及几乎任何其他内容,我将向您指出(我认为 DSQL 的事实上的指南)Erland Sommarskog 撰写的 The Curse and Blessings of Dynamic SQL