【问题标题】:Join to Table-valued Function failing加入表值函数失败
【发布时间】:2013-08-07 08:53:35
【问题描述】:

我遇到了一个连接失败的表值函数,我无法解释它。我在下面创建了一个测试脚本,并在 SQL Server 2008 R2 上运行它

谁能理解为什么在测试脚本结束时第一个 SELECT 语句有效而第二个语句无效?

CREATE TABLE dbo.Test (Setting INT NOT NULL, Value NVARCHAR(MAX) NULL)

GO

INSERT  dbo.Test (Setting, Value)
SELECT  3151, '2~-10011;2~-10012'

GO

CREATE FUNCTION [dbo].[CTESplitChunk] (@list  nvarchar(MAX),
                                 @delim nchar(1) = ',')
RETURNS @t TABLE (str nvarchar(4000) NOT NULL) AS
BEGIN
   DECLARE @slice nvarchar(4000),
           @textpos int,
           @maxlen  int,
           @stoppos int,
           @lastone bit

   SELECT @textpos = 1, @maxlen = 4000 - 2, @lastone = 0
   WHILE @lastone = 0
   BEGIN
      IF datalength(@list) / 2 - (@textpos - 1) >= @maxlen
      BEGIN
         SELECT @slice = substring(@list, @textpos, @maxlen)
         SELECT @stoppos = @maxlen -
                           charindex(@delim COLLATE Slovenian_BIN2, reverse(@slice))
         SELECT @slice = left(@slice, @stoppos) + @delim
         SELECT @textpos = @textpos - 1 + @stoppos + 2   -- On the other side of the comma.
      END
      ELSE
         SELECT @slice = substring(@list, @textpos, @maxlen) + @delim,
                @lastone = 1

      ;WITH csvtbl(start, stop) AS (
         SELECT start = 1,
                stop  = charindex(@delim COLLATE Slovenian_BIN2, @slice)
         UNION ALL
         SELECT start = stop + 1,
                stop  = charindex(@delim COLLATE Slovenian_BIN2,
                                  @slice, stop + 1)
         FROM   csvtbl
         WHERE  stop > 0
      )
      INSERT @t (str)
         SELECT ltrim(rtrim(
                substring(@slice, start,
                          CASE WHEN stop > 0 THEN stop - start ELSE 0 END)))
         FROM   csvtbl
         WHERE  stop > 0
         OPTION (MAXRECURSION 0)
   END

   RETURN
END

GO

SELECT          Value
FROM            dbo.Test t
WHERE           t.Setting = '3151'

GO

SELECT          Value
FROM            dbo.Test t
    INNER JOIN  dbo.CTESplitChunk (t.Value, ';') s ON 1 = 1
WHERE           t.Setting = '3151'

【问题讨论】:

    标签: sql-server-2008 user-defined-functions


    【解决方案1】:

    您需要CROSS APPLY 来调用具有相关参数的 TVF。

    SELECT t.Value,
           s.*
    FROM   dbo.Test t
           CROSS APPLY dbo.CTESplitChunk (t.Value, ';') s
    WHERE  t.Setting = '3151' 
    

    【讨论】:

    • 是的,谢谢 - 发帖后我才恍然大悟!男生错误:-)
    • 现在您已将CROSS APPLY 添加到问题的代码中,这个答案看起来很奇怪。关于为什么加入某些可以根据t.Value 更改其内容的表表达式没有意义。内连接应该是可交换的。你怎么能从 TVF 推动加入?
    • 明白 - 我在看到你的答案之前添加了这一点 - 我将删除编辑以供将来参考。
    猜你喜欢
    • 1970-01-01
    • 2016-07-13
    • 2011-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多