注意:
这篇文章是专门针对人们已经熟悉了SQLCMD模式在SQL Server Management Studio中。虽然不是非常新颖的,读者应该明白SQLCMD文档中的基本功能。
若对DOS命令Shell有一个基本的了解,也将让你更好的理解下面这些例子。
步骤概述:
步骤概述:
本文用于处理动态生成文件,虽然我们在同一个脚本中创建和运行文件,但是随着复杂度的提升结果将会难以预测。所以,公在允许意外丢失的情况下运行该例子。
不,SQLCMD我已经试过了...
如果你像我一样,你可能花了数年进出SQL Server Management Studio中的SQLCMD模式。它有一些很好的功能,但其激活带着禁用智能感知的成本。就个人而言,我总是最后关闭它,并忘记它了好几个月......直到现在...
在接下来的几个职位,我将讲到所有之前使你放弃了SQLCMD模式的ukjg。我的目标不是让你保持在SSMS中的按钮激活,而是为了增强能力,你将永远不会再忘记。
如果你像我一样,你可能花了数年进出SQL Server Management Studio中的SQLCMD模式。它有一些很好的功能,但其激活带着禁用智能感知的成本。就个人而言,我总是最后关闭它,并忘记它了好几个月......直到现在...
在接下来的几个职位,我将讲到所有之前使你放弃了SQLCMD模式的ukjg。我的目标不是让你保持在SSMS中的按钮激活,而是为了增强能力,你将永远不会再忘记。
文章的开头,我们先解决变量 setvary变量无力 问题。第二部分,我将很快搬出命令shell基础知识,并为作为第三节,快乐真正开始的地方为背景。在第三节我会告诉你怎么写20行代码来创建一个示例包含450万个独特的名字的“perosn”表。
噢...我没有使用智能感知与SQLCMD模式的解决方案,但它仍然是值得的....
不能以编程方式设置变量
SQLCMD模式下,可以设置基于文本值的变量。不幸的是,你不能设置基于SQL Server的输出变量。它也不可能通过其他SQLCMD变量串联或环境变量。
SQLCMD模式下,可以设置基于文本值的变量。不幸的是,你不能设置基于SQL Server的输出变量。它也不可能通过其他SQLCMD变量串联或环境变量。
(This is not supported)
:SETVAR FileName (SELECT @@Servername + '.txt')
:SETVAR NewVar $(OldVar1)$(OldVar2)
(This is not supported)
通过程序生成一个“变量文件”
下面的脚本将生成一个系统中的临时文件夹名为“ GetServerName.sql ”的文件。该文件的内容,一个SETVAR命令,然后将来自同一脚本读取。
执行“ GetServerName ”之后,我们将使用我们的新的变量$ (文件路径)来创建系统用户( server_principals )的测试文件。
只是为了好玩,我们也将打开这两个文件在年底对其进行审查记事本。请记住, 关闭记事本,不然SQL会一直正在运行。
下面的脚本将生成一个系统中的临时文件夹名为“ GetServerName.sql ”的文件。该文件的内容,一个SETVAR命令,然后将来自同一脚本读取。
执行“ GetServerName ”之后,我们将使用我们的新的变量$ (文件路径)来创建系统用户( server_principals )的测试文件。
只是为了好玩,我们也将打开这两个文件在年底对其进行审查记事本。请记住, 关闭记事本,不然SQL会一直正在运行。
:OUT $(TEMP)\GetServerName.sql
PRINT ':SETVAR FilePath $(TEMP)\' + @@SERVERNAME + '.txt'
GO
:OUT stdout
:r $(TEMP)\GetServerName.sql
GO
:OUT $(FilePath)
SELECT name, create_date
FROM master.sys.server_principals
GO
:OUT stdout
!!notepad $(TEMP)\GetServerName.sql
!!notepad $(FilePath)
注意:
- 注意文件路径时,记事本打开的第一个文件( GetServerName.sql ) 。注意,系统参数, $ ( TEMP ) ,已经解决了自己的临时目录的完整路径。
- 要知道一个变量前面,因为它的行为就像一个转义字符,否定接下来的变量$反斜杠字符( \ )的。
SQLCMD中,有没有条件(if/then)逻辑?
真的!我们如何解决这个问题?我们要解决这一个与另一个动态生成的文件。
假设我们想批量导入本地文件,运行BCP ,或处理一组的其他SQLCMD功能。如果我们的目标文件不存在,我们通常没有办法退出脚本。然而,我们可以使用DOS命令来执行类似的操作,以与前面例子中。为此,我们生成一个包含两个脚本一个文件(根据条件得到满足) 。我们首先创建一个“false/ Exit(退出) ”文件。当我们执行,我们替换该文件,当我们取得成功。
真的!我们如何解决这个问题?我们要解决这一个与另一个动态生成的文件。
假设我们想批量导入本地文件,运行BCP ,或处理一组的其他SQLCMD功能。如果我们的目标文件不存在,我们通常没有办法退出脚本。然而,我们可以使用DOS命令来执行类似的操作,以与前面例子中。为此,我们生成一个包含两个脚本一个文件(根据条件得到满足) 。我们首先创建一个“false/ Exit(退出) ”文件。当我们执行,我们替换该文件,当我们取得成功。
-- SQLCMD Error Handling
:setvar ErrorCheckFile "ErrorCheckFile.sql"
-- Set DOS commands that will display in the output window and run SQLCMD EXIT.
:setvar ErrorStatusCommand "(ECHO !!ECHO ValidationFailure. Terminating Script. && ECHO :Exit)"
-- The following line creates the file. Use this line for each situation that might require us to stop.
!! $(ErrorStatusCommand) > $(TEMP)$(ErrorCheckFile)
-- See if a file exists. If so, replace our EXIT command with a blank file.
!! If EXIST $(TEMP)\*.* @ECHO. > $(TEMP)$(ErrorCheckFile)
-- Now read/execute the result
:r $(TEMP)$(ErrorCheckFile)
!! ECHO Found files in the Temp folder (this is normal).
!! ECHO.
!! ECHO Checking Next File.
-- Reset the file back to Exit
!! $(ErrorStatusCommand) > $(TEMP)$(ErrorCheckFile)
-- Try again with a file that shouldn't exist
!! If EXIST $(TEMP)\ThisFileShouldNotBeHere.txt @ECHO. > $(TEMP)$(ErrorCheckFile)
-- Now read/execute the result
:r $(TEMP)$(ErrorCheckFile)
!! ECHO You should not see this.
PRINT 'You should not see this either'
如果我们的脚本运行正确,输出窗口将包含以下内容:
Found files in the Temp folder (this is normal).
Checking Next File.
ValidationFailure. Terminating Script.
好吧...花式DOS技巧......是不是这样?
没了。这是我们开始有乐趣。我们将采取它在接下来的文章中的水平,但我们需要先做基础。现在,我将离开你的方式来执行循环。
SET NOCOUNT ON
IF OBJECT_ID('tempdb..#state') IS NULL
BEGIN
CREATE TABLE #state(TheStart DATETIME2)
INSERT #state VALUES(DATEADD(S, 1, SYSDATETIME()))
END
GO
PRINT 'Beginning Loop1'
GO
DECLARE @TimeRemaining INT
SELECT TOP 1 @TimeRemaining = DATEDIFF(MS, SYSDATETIME(), TheStart) FROM #state
PRINT CAST(@TimeRemaining AS VARCHAR) + ' milliseconds to go...'
GO
:out $(TEMP)\loop2.sql
IF SYSDATETIME() <=(SELECT TOP 1 TheStart FROM #state)
BEGIN
PRINT 'PRINT ''Hello from loop2'''
PRINT ':r $(TEMP)\loop.sql'
END
ELSE
BEGIN
PRINT 'PRINT ''Last visit to Loop2!'''
PRINT 'DROP TABLE #state'
END
GO
:out STDOUT
WAITFOR DELAY '0:00:00.1'
GO
PRINT 'Running loop-checker...'
GO
:r $(TEMP)\loop2.sql
有关调试最后需要说明的
从我的经验与SQLCMD模式,意想不到的结果的最常见的原因是由于缺失GO语句或不插入线之间的空白。
- SQLCMD爱的空白。如果你的命令无法正常工作,尝试将它上面下面加空格...
- SQLCMD也爱来解析一切,也不会想要的SQL引擎返回的响应。如果您需要SQLCMD与来自SQL Server的输出工作,扔在一个GO语句。
- 切记不要把反斜杠在变量名的前面。这并不工作: $ ( TEMP ) \ $ (文件名)
- 添加更多的垂直空间。添加更多的GO语句。
ssms中打开sqlcmd
my code
我的情况