传递文字?到 sp_MSforeachdb

Jos*_*ley 6 sql-server t-sql

我正在尝试搜索?字符串中的字符,但在服务器上的所有数据库中搜索。由于?标记是数据库名称的占位符,我如何格式化查询以便它知道我的意思是搜索?而不是用数据库名称替换它?

此时的 WHERE 子句是:

WHERE DirectoryPath LIKE ''%?%''
Run Code Online (Sandbox Code Playgroud)

这导致:

WHERE DirectoryPath LIKE '%DATABASENAME%'
Run Code Online (Sandbox Code Playgroud)

我需要它呈现为:

WHERE DirectoryPath LIKE '%?%'
Run Code Online (Sandbox Code Playgroud)

Aar*_*and 7

感谢马丁更新。如果您查看该过程的文本:

EXEC sys.sp_helptext N'sp_MSforeachdb';
Run Code Online (Sandbox Code Playgroud)

您将看到它将@replacecharas NCHAR(1)(默认N'?')传递到sys.sp_MSforeach_worker. 剥开洋葱的另一层,您会看到该过程中的代码非常丑陋,该代码循环遍历命令中的每个字符并重建它。我没有研究每一行,但我找不到任何有条件地转义或保留实际问号的能力的证据,除非 - 正如马丁指出的 - 你用一个不同的字符覆盖它,该字符不能自然出现在命令。所以也许是这样的:

EXEC sp_MSforeachdb N'SELECT ''?'', other_columns FROM [?].dbo.whatever
  WHERE DirectoryPath LIKE ''%?%'';', N'?';

-- ? is NCHAR(420), chosen randomly
Run Code Online (Sandbox Code Playgroud)

由于它确实在寻找文字?字符,因此可能更简单的方法是:

EXEC sys.sp_MSforeachdb N'PRINT ''?'' + ''-'' +  CONVERT(VARCHAR(32), 0x3F)';
Run Code Online (Sandbox Code Playgroud)

因此推断,我们可以构建这个丑陋的变体:

EXEC sys.sp_MSforeachdb N'SELECT ''?'', other_columns FROM [?].dbo.whatever
  WHERE DirectoryPath LIKE ''%'' + CONVERT(VARCHAR(32), 0x3F) + ''%'';';
Run Code Online (Sandbox Code Playgroud)

话虽如此,您可以编写自己的版本,sp_MSforeachdb该版本使用不同的默认值@replacechar,因此您不必手动覆盖它。您可能应该编写自己的版本而不是依赖内置程序,正如我在这些帖子中指出的那样 - 它不受支持,没有记录,并且实际上有一个非常高频率的错误,由于游标选项,它会跳过数据库用过的:

  • `@replacechar` 被传递到 `sp_MSforeachdb` 以及第二个参数,所以 `EXEC sp_MSforeachdb N'SELECT ''?!?''', N'!'` 工作正常。 (2认同)