将一列拆分为多个命名列

时间:2013-08-15 16:42:41

标签: sql sql-server-2008-r2

在最近的恢复和问题发生之前可能会或可能不会出现,但是现在我已经意识到这一点,我的任务是找到解决方案。我们通常将数据写入每行的多个列名称,但是我发现所有字段都将转到溢出列。以下是我们所拥有的一个例子。

我们应该有数据列:

fldDate - fldName    - fldPhoneNumber - fldTransactionID - fldOverflow    
8/15/13 - John Smith - 1012023344     - 123456789        - Null

我们得到了什么:

fldDate - fldName    - fldPhoneNumber - fldTransactionID - fldOverflow   
8/15/13 - null       - null           - null             - fldName="John Smith", fldPhoneNumber="1012023344", fldTransactionID="123456789"

我需要什么:

我需要找到一种方法将fldOverflow字段数据恢复到正确的字段中。任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:0)

有许多函数用于将分隔字段分成多个列,因此这是一个选项,您还可以使用COALESCE()和字符串操作,例如:

SELECT  fldDate 
      , fldName = COALESCE(fldName, SUBSTRING(fldOverflow,CHARINDEX('fldName="',fldOverflow)+9,CHARINDEX(', fldPhone',fldOverflow)-CHARINDEX('fldName="',fldOverflow)-10))
      , fldPhoneNumber 
      , fldTransactionID
      , fldOverflow 
FROM Table

答案 1 :(得分:0)

我会将fldOverflow值转换为xml,然后我会使用UPDATE:

DECLARE @MyTable TABLE(
    fldName          NVARCHAR(50),
    fldPhoneNumber   VARCHAR(20),
    fldTransactionID INT,
    fldOverflow      NVARCHAR(4000)
);
INSERT INTO @MyTable (fldOverflow)
VALUES (N'fldName="John Smith", fldPhoneNumber="1012023344", fldTransactionID="123456789"');

PRINT 'Before:'
SELECT  *
FROM    @MyTable;

-- I would use, also, transactions thus
-- BEGIN TRANSACTION
UPDATE  x
SET     fldName         =z.fldName,
        fldPhoneNumber  =z.fldPhoneNumber,
        fldTransactionID=z.fldTransactionID,
        fldOverflow     =NULL
-- OUTPUT   deleted.fldName AS OldfldName,inserted.fldName AS NewfldName, ...
FROM    @MyTable x
CROSS APPLY
(
    SELECT  y.XmlFragment.value('(/row/@fldName)[1]','NVARCHAR(50)') AS fldName,
            y.XmlFragment.value('(/row/@fldPhoneNumber)[1]','VARCHAR(20)') AS fldPhoneNumber,
            y.XmlFragment.value('(/row/@fldTransactionID)[1]','INT') AS fldTransactionID
    FROM
    (
        SELECT CONVERT(XML,'<row '+REPLACE(x.fldOverflow,',', ' ')+' />') AS XmlFragment
    ) y
) z
WHERE   x.fldOverflow IS NOT NULL;
-- ROLLBACK TRANSACTION
-- -- COMMIT TRANSACTION

PRINT 'After:'
SELECT  *
FROM    @MyTable;

结果:

Before:
fldName     fldPhoneNumber  fldTransactionID fldOverflow
----------- --------------- ---------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
NULL        NULL            NULL             fldName="John Smith", fldPhoneNumber="1012023344", fldTransactionID="123456789"

After:
fldName     fldPhoneNumber  fldTransactionID fldOverflow
----------- --------------- ---------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
John Smith  1012023344      123456789        NULL

修改1:

SELECT  x.fldName AS OldfldName,z.fldName AS NewfldName, ...
FROM    @MyTable x
CROSS APPLY
(
    SELECT  y.XmlFragment.value('(/row/@fldName)[1]','NVARCHAR(50)') AS fldName,
            y.XmlFragment.value('(/row/@fldPhoneNumber)[1]','VARCHAR(20)') AS fldPhoneNumber,
            y.XmlFragment.value('(/row/@fldTransactionID)[1]','INT') AS fldTransactionID
    FROM
    (
        SELECT CONVERT(XML,'<row '+REPLACE(x.fldOverflow,',', ' ')+' />') AS XmlFragment
    ) y
) z
WHERE   x.fldOverflow IS NOT NULL;