1

我創建了一個用戶定義的表類型:操作數類型衝突:VARCHAR是不符合用戶定義的表型

CREATE TYPE dbo.ListTableType AS TABLE(
    ITEM varchar(500) NULL 
) 

我利用它的功能:

CREATE FUNCTION dbo.fn_list_to_string 
(
    @LIST dbo.ListTableType READONLY 
) 
RETURNS varchar(max) 
AS 
BEGIN 
    DECLARE @RESULT varchar(max) 
    SET @RESULT = '' 

    DECLARE @NL AS CHAR(2) = CHAR(13) + CHAR(10) 

    SELECT @RESULT = @RESULT + ITEM + @NL FROM @LIST 
    SET @RESULT = SUBSTRING(@RESULT, 1, LEN(@RESULT) - 1) 

    RETURN @RESULT 
END 

最後,我嘗試在一個簡單的使用此功能選擇:

SELECT 
    P.PROGRAM_ID, 
    PROGRAM_NAME, 
    PROGRAM_DESC, 
    P.STATUS_ID, 
    STATUS_DESC, 
    P.CONTACT_SID, 
    I.FIRST_NAME + ' ' + I.LAST_NAME as CONTACT_NAME, 
    P.CLARITY_ID, 
    dbo.fn_list_to_string(
     ( SELECT CONVERT(varchar,CLARITY_ID) as ITEM 
      FROM dbo.MUSEUM_PROGRAM_PROJECTS as A 
      JOIN dbo.MUSEUM_PROJECTS as B on B.PROJECT_ID = A.PROJECT_ID 
      WHERE PROGRAM_ID = P.PROGRAM_ID) 
    ) as PROJECT_CLARITY_IDS 
FROM dbo.MUSEUM_PROGRAMS as P 
LEFT JOIN dbo.MUSEUM_PROGRAM_STATUS_TYPES as S on S.STATUS_ID = P.STATUS_ID 
LEFT JOIN dbo.v_IDVAULT_ENRICHED_CURRENT_EMPLOYEES as I on I.[SID] = P.CONTACT_SID 

但我得到這個錯誤:

Operand type clash: varchar is incompatible with ListTableType

任何想法爲什麼?此外,如果還有另一種[更優雅]的方式來實現我正在嘗試做的事情,我也樂於接受建議!提前致謝!

+2

(1)不要使用'varchar'不長( http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/09/bad-habits-to-kick-declaring-varchar-without-length.aspx)(2)你不能用子查詢代替表類型的函數輸入,使它看起來像你實際上有一個表類型。我建議你發佈你實際想要得到的結果,我認爲用'FOR XML PATH'有一種更簡單的方法。 –

+0

例如,子查詢可以返回兩個CLARITY_ID:25245 和14355.我想用一個新行顯示這個字符串。 – elisa

+0

搜索SQL Server中的「GROUP_CONCAT」攻擊以將列表投影到標量varchar中,例如http://stackoverflow.com/questions/8868604/sql-group-concat-function-in-sql-server。但你的想法很有趣:) – StuartLC

回答

2

這裏是FOR XML PATH技術,它做這一切有一個非常簡單的子查詢,並沒有表類型或極其低效的多語句表值函數等

USE tempdb; 
GO 

CREATE TABLE dbo.P(Program_ID INT); 

CREATE TABLE dbo.M(Clarity_ID INT, Program_ID INT); 

INSERT dbo.P VALUES(1),(2),(3),(4); 

INSERT dbo.M VALUES(1,1),(1,2),(2,3),(3,2),(1,4),(4,1); 

SELECT 
    P.PROGRAM_ID, 
    PROJECT_CLARITY_IDS = STUFF((
     SELECT CHAR(13)+CHAR(10)+CONVERT(VARCHAR(12),Clarity_ID) 
     FROM dbo.M WHERE Program_ID = p.Program_ID 
     FOR XML PATH(''), TYPE).value('.[1]','nvarchar(max)'),1,2,'') 
FROM dbo.P AS p; 

SQLfiddle demo

簡單演示

輸出在SQLfiddle或Management Studio中的網格結果中看起來不正確,因爲它們會將回車符/換行符用於顯示目的,但可以用兩個逗號或分號替換CHAR(13)+CHAR(10)或其他內容以驗證那裏是兩個字符在那裏。

0

使用STUFF..FOR XML PATH與CTE結合進行concatanation時,會得到您想要的結果。事情是這樣的:

WITH CTE_PROJECT_CLARITIES AS 
(
    SELECT DISTINCT PROGRAM_ID 
      , STUFF((
       SELECT CHAR(13) + CHAR(10) + CONVERT(varchar(11),CLARITY_ID) 
       FROM dbo.MUSEUM_PROGRAM_PROJECTS as A 
        JOIN dbo.MUSEUM_PROJECTS as B on B.PROJECT_ID = A.PROJECT_ID 
       WHERE A.PROGRAM_ID = X.PROGRAM_ID 
       FOR XML PATH ('')),1,2,'') AS PROJECT_CLARITY_IDS 
    FROM MUSEUM_PROGRAM_PROJECTS X 
) 
SELECT 
    P.PROGRAM_ID, 
    PROGRAM_NAME, 
    PROGRAM_DESC, 
    P.STATUS_ID, 
    STATUS_DESC, 
    P.CONTACT_SID, 
    I.FIRST_NAME + ' ' + I.LAST_NAME as CONTACT_NAME, 
    P.CLARITY_ID, 
    X.PROJECT_CLARITY_IDS 
FROM dbo.MUSEUM_PROGRAMS as P 
LEFT JOIN dbo.MUSEUM_PROGRAM_STATUS_TYPES as S on S.STATUS_ID = P.STATUS_ID 
LEFT JOIN dbo.v_IDVAULT_ENRICHED_CURRENT_EMPLOYEES as I on I.[SID] = P.CONTACT_SID 
LEFT JOIN CTE_PROJECT_CLARITIES X ON X.PROGRAM_ID = p.PROGRAM_ID 

SQLFiddle DEMO(不知道如果我得到正確的列,但你的想法)

+0

我確實按照Aaron Bertrand的建議去了FOR XML PATH路線,但由於select語句在視圖中,所以不能使用CTE。 – elisa

+0

@elsia我看不到如何在視圖中選擇語句可以防止使用CTE。 –

+0

@elisa [爲什麼不能查看包含CTE](http://sqlfiddle.com/#!3/cd2c6/1)? –

相關問題