是否可以在 sql-server 2008 中创建一个将一行分成多行的视图?
Is it possible to have a view in sql-server 2008 that splits one row into many?
背后的故事是我正在尝试编写一个视图,该视图采用 table 谁的每一行都是一个 ID 和该 ID 在 clob 中的序列化数据,并以 sql 可导航的形式呈现.基本上我的代码看起来像:
CREATE VIEW UNSERIALIZED_TABLE_VIEW AS
SELECT
SOURCE_TABLE.ID SOURCE_ID,
a.*
FROM
SOURCE_TABLE,
FUNCTION_WHICH_UNSERIALIZES((SELECT DATA FROM SOURCE_TABLE WHERE ID = SOURCE_ID)
我尝试将函数放在 select 语句中,但这只是给出了一个关于它未定义的语法错误。当它运行时,错误通常是关于子查询返回太多值。我可以批量反序列化数据,但现在我真的很好奇出了什么问题。
示例数据
@0History:23:ALPHANUMERICSTUFF1234567ID:11:ACCT1234567SourceMode:6:ANNUAL.ModeChanges:UniqueIndex:23:ALPHANUMERICSTUFF1234567ID:11:ACCT1234567OldValue:1:+NewValue:6:ANNUALChangeType:1:AChangeDate:20:6/03/2013 2:49:32 AM.
@0History:UniqueIndex:95:NOTTHESAME0987654|ALPHANUMERIC534|PRETEND349235|95CHARACTERSID:47:GNR44718500|PNR48CDQ704|PGP48090798|FGDS2345236SourceMode:26:ANNUAL|C-P-D|ANNUAL|ANNUALLoan:3:|||ModeChanges:UniqueIndex:95:00487SOMETHING4264500ORD|992581PROBABLY04ORD|0048SHOULD238BET|0095CHARS436PR638FGP07VDCID:47:GNR44718500|PNR48CDQ704|PGP48090798|FGDS2345236OldValue:7:+|+|+|+NewValue:26:ANNUAL|C-P-D|ANNUAL|ANNUALChangeType:7:A|A|A|AChangeDate:91:12/22/2013 11:53:11 PM|4/22/2013 11:53:11 PM|12/22/2013 11:53:11 PM|12/22/2013 11:53:11 PM.
数据被序列化 table 形式为 COLUMN_NAME:LENGTH_OF_ENTRY:DATA_FOR_COLUMN_ROW_1|DATA_FOR_COLUMN_ROW2|....NEXT_COLUMN_NAME...
的数据
函数示例:
CREATE FUNCTION FUNCTION_THAT_UNSERIALIZES (@clob varchar(max),@colname varchar(max)) RETURNS @NewValue TABLE (ID INT,value varchar(max)) AS
BEGIN
DECLARE @colstart INT,@lenstart INT,@lenend INT,@collen VARCHAR(MAX),@lngth INT,@tmp VARCHAR(MAX), @rowid INT,@value VARCHAR(max),@next INT;
SELECT
@colstart = CHARINDEX(@colname,@tmp)+1,
@lenstart = CHARINDEX(':',@tmp,@colstart)+1,
@lenend = CHARINDEX(':',@tmp,@lenstart),
@collen = SUBSTRING(@tmp,@lenstart,@lenend - @lenstart),
@lngth = CAST (@collen AS INT),
@tmp = SUBSTRING(@tmp,@lenend,@lngth);
WHILE LEN(@tmp) > 0 BEGIN
SET @next = CHARINDEX('|',@tmp);
IF @next > 0 BEGIN
SET @value = SUBSTRING(@tmp,0,@next);
SET @tmp = SUBSTRING(@tmp,@next+1,LEN(@tmp) - @next);
END ELSE BEGIN
SET @value = @tmp;
SET @tmp = '';
END
INSERT INTO @NewValue VALUES(@rowid,@value)
SET @rowid = @rowid+1;
END
RETURN
示例错误
Msg 512, Level 16, State 1, Line 7
子查询返回了 1 个以上的值。当子查询跟在 =、!=、<、<=、>、>= 或子查询用作表达式时,这是不允许的。
Msg 4104, Level 16, State 1, Line 15
无法绑定多部分标识符 "SOURCE_TABLE.SOURCE_ID"。
..我认为可能还有另一个,但现在无法弄清楚如何重现它。
我认为这可能是您完成我认为您正在尝试做的事情所需的语法。
CREATE VIEW UNSERIALIZED_TABLE_VIEW AS
SELECT
SOURCE_TABLE.ID SOURCE_ID,
a.*
FROM SOURCE_TABLE
CROSS APPLY FUNCTION_WHICH_UNSERIALIZES(DATA, @colname) a
我不确定你的@colname 参数应该是什么;它被排除在问题的代码之外。
背后的故事是我正在尝试编写一个视图,该视图采用 table 谁的每一行都是一个 ID 和该 ID 在 clob 中的序列化数据,并以 sql 可导航的形式呈现.基本上我的代码看起来像:
CREATE VIEW UNSERIALIZED_TABLE_VIEW AS
SELECT
SOURCE_TABLE.ID SOURCE_ID,
a.*
FROM
SOURCE_TABLE,
FUNCTION_WHICH_UNSERIALIZES((SELECT DATA FROM SOURCE_TABLE WHERE ID = SOURCE_ID)
我尝试将函数放在 select 语句中,但这只是给出了一个关于它未定义的语法错误。当它运行时,错误通常是关于子查询返回太多值。我可以批量反序列化数据,但现在我真的很好奇出了什么问题。
示例数据
@0History:23:ALPHANUMERICSTUFF1234567ID:11:ACCT1234567SourceMode:6:ANNUAL.ModeChanges:UniqueIndex:23:ALPHANUMERICSTUFF1234567ID:11:ACCT1234567OldValue:1:+NewValue:6:ANNUALChangeType:1:AChangeDate:20:6/03/2013 2:49:32 AM.
@0History:UniqueIndex:95:NOTTHESAME0987654|ALPHANUMERIC534|PRETEND349235|95CHARACTERSID:47:GNR44718500|PNR48CDQ704|PGP48090798|FGDS2345236SourceMode:26:ANNUAL|C-P-D|ANNUAL|ANNUALLoan:3:|||ModeChanges:UniqueIndex:95:00487SOMETHING4264500ORD|992581PROBABLY04ORD|0048SHOULD238BET|0095CHARS436PR638FGP07VDCID:47:GNR44718500|PNR48CDQ704|PGP48090798|FGDS2345236OldValue:7:+|+|+|+NewValue:26:ANNUAL|C-P-D|ANNUAL|ANNUALChangeType:7:A|A|A|AChangeDate:91:12/22/2013 11:53:11 PM|4/22/2013 11:53:11 PM|12/22/2013 11:53:11 PM|12/22/2013 11:53:11 PM.
数据被序列化 table 形式为 COLUMN_NAME:LENGTH_OF_ENTRY:DATA_FOR_COLUMN_ROW_1|DATA_FOR_COLUMN_ROW2|....NEXT_COLUMN_NAME...
的数据函数示例:
CREATE FUNCTION FUNCTION_THAT_UNSERIALIZES (@clob varchar(max),@colname varchar(max)) RETURNS @NewValue TABLE (ID INT,value varchar(max)) AS
BEGIN
DECLARE @colstart INT,@lenstart INT,@lenend INT,@collen VARCHAR(MAX),@lngth INT,@tmp VARCHAR(MAX), @rowid INT,@value VARCHAR(max),@next INT;
SELECT
@colstart = CHARINDEX(@colname,@tmp)+1,
@lenstart = CHARINDEX(':',@tmp,@colstart)+1,
@lenend = CHARINDEX(':',@tmp,@lenstart),
@collen = SUBSTRING(@tmp,@lenstart,@lenend - @lenstart),
@lngth = CAST (@collen AS INT),
@tmp = SUBSTRING(@tmp,@lenend,@lngth);
WHILE LEN(@tmp) > 0 BEGIN
SET @next = CHARINDEX('|',@tmp);
IF @next > 0 BEGIN
SET @value = SUBSTRING(@tmp,0,@next);
SET @tmp = SUBSTRING(@tmp,@next+1,LEN(@tmp) - @next);
END ELSE BEGIN
SET @value = @tmp;
SET @tmp = '';
END
INSERT INTO @NewValue VALUES(@rowid,@value)
SET @rowid = @rowid+1;
END
RETURN
示例错误
Msg 512, Level 16, State 1, Line 7
子查询返回了 1 个以上的值。当子查询跟在 =、!=、<、<=、>、>= 或子查询用作表达式时,这是不允许的。
Msg 4104, Level 16, State 1, Line 15
无法绑定多部分标识符 "SOURCE_TABLE.SOURCE_ID"。
..我认为可能还有另一个,但现在无法弄清楚如何重现它。
我认为这可能是您完成我认为您正在尝试做的事情所需的语法。
CREATE VIEW UNSERIALIZED_TABLE_VIEW AS
SELECT
SOURCE_TABLE.ID SOURCE_ID,
a.*
FROM SOURCE_TABLE
CROSS APPLY FUNCTION_WHICH_UNSERIALIZES(DATA, @colname) a
我不确定你的@colname 参数应该是什么;它被排除在问题的代码之外。