我有 2 个名称列的表:
CREATE TABLE Test
(
TestID int identity primary key clustered
, Name_Eng nvarchar(50)
, Name_Nat nvarchar(50)
)
现在我需要一个查询来使该Name
列用 分隔,
,如下所示:
DECLARE @NameColumns NVARCHAR(1024)
SET @NameColumns = STUFF(
(SELECT ',' + 'Test.' + name AS [text()]
FROM ( SELECT c.name
FROM sys.columns c
INNER JOIN sys.tables t ON t.object_id = c.object_id
WHERE t.name = 'Test'
AND c.name LIKE 'Name_%'
) AS D
FOR XML PATH('') ,
TYPE).value('.[1]', 'VARCHAR(MAX)'), 1, 1,
N'')
select @NameColumns
但是这个查询在执行计划中有一个警告:
有什么办法可以消除这个警告吗?
由于 XML 函数,警告就在那里
value()
。第二个参数 tovalue()
是您希望将存储在 XML 中的值转换为的值。您可能会争辩说,这实际上不是隐式转换,而是非常显式的转换,因为您要求它发生。可能需要向 Microsoft 建议的连接项目。重现您所看到的最简单的方法。
给出这两个警告。
如您所见,您也可以使用 int 获得它,并且每次调用
value()
.转换是在 Stream Aggregate 运算符中完成的,该运算符计算这样的值。
表值函数的结果在
lvalue
orvalue
列中返回。该表达式通过使用datalength
来检查它应该从哪里获取,然后将其转换为您想要的数据类型。就在这里。从语句中删除
TYPE
指令FOR XML PATH
并删除对value()
函数的调用。这样做的一个副作用是,您连接的包含需要在 XML 中编码的字符的值&<>
将被编码到您的结果中。虽然我同意@Kin 关于数据类型的观点,但我认为这个警告并不像你想象的那么麻烦。您正在执行分组连接,无论如何这将比任何转换都贵几个数量级(正如丹尼尔所说,除非您的目录视图很大 - 例如大于物理内存 - 它不太可能影响任何方面估计)。
我会以这种方式编写查询,注意不要使用 varchar 字符串(这也意味着停止省略
N
字符串文字的前缀),并确保您使用语句终止符:即使如此,我也不相信有任何方法可以避免隐式转换而不改变输出,如 Mikael 建议的那样避免
TYPE
/value()
。当您实际上可以证明这对查询的性能有一些实质性影响时,我会说担心这一点。在我的测试中,两种不同的形式执行相同(我们每次都在 10 毫秒以下),但当然,如果我有一个名为的表Sales & Stuff
,那么它就Sales & Stuff
没有隐式转换。查询计划中的警告意味着,由于您有隐式数据类型转换,SQL Server 将无法准确猜测返回的正确行数,这反过来可能导致计划不够优化。
这对于必须执行良好的查询很重要,通常是因为它们处理大量数据,但在您的情况下,情况似乎并非如此,因为您只是在查询
sys.tables
和sys.columns
.对您的问题的简短回答是:除非您的数据库中有数以百万计的表和列,否则这无关紧要。