在 xquery sql 服务器中组合多个文字子串
Combine multiple literal substring in xquery sql server
在SQL 服务器中,我试图通过索引获取数组元素。
我通过将字符串转换为 XML 然后通过索引调用它来做到这一点。
SELECT CAST('<D>A1</D><D>a2</D>' AS XML).value('/D[1]','varchar(15)')
我的问题是我想在 '/D[1]'
中有一个数组索引作为输入参数。当我想将输入索引作为来自 table 的列时,这很有用,如下所示:
SELECT CAST('<D>A1</D><D>a2</D>' AS XML).value('/D['+COLUMN_WITH_INT_INDEX+']','varchar(15)') FROM TABLE_X
但是,这不起作用。我收到一条错误消息说
The argument 1 of the XML data type method "value" must be a string literal.
所有将 '/D['+COLUMN_WITH_INDEX+']'
转换为字符串文字的尝试都失败了。
您可以使用 sp_executesql 绕过“必须是文字”的约束,方法是将变量作为文字放入字符串中。
不过,您确实需要 运行 每个不同值的变体。
我在下面的示例中使用了两个过程。第一个处理索引的单个值并过滤掉索引不同或没有结果的任何记录。
create procedure proc_run_for_one (@i int) as
begin
declare @stmt nvarchar(max);
set @stmt = 'SELECT source, ' +
' cast(@i as nvarchar) + ',' +
' CAST(source AS XML).value(''/D['
+ cast(@i as nvarchar) + ']'',''varchar(15)'')
' FROM source_data '+
' WHERE i = ' + cast(@i as nvarchar) +
' AND CAST(source AS XML).value(''/D[' +
cast(@i as nvarchar) +
']'',''varchar(15)'') IS NOT NUll' ;
insert into target
exec sp_executesql @stmt;
end;
go
而第二个过程 运行 是每个值的第一个过程。我在这里使用了一个简单的计数器,但是 select distinct 可能会更有效,因为它只需要命中实际存在的值。
create procedure proc_run_for_all as
begin
declare @min int, @max int, @current int;
select @min = MIN(i), @max = MAX(i) FROM source_data;
set @current = @min;
while @current <= @max
begin
exec proc_run_for_one @current
set @current = @current + 1
end;
end;
go
表格和示例数据是
create table source_data (source nvarchar(max), i int)
go
insert into source_data values ('<D>A1</D><D>a2</D>',1)
go
insert into source_data values ('<D>A1</D><D>a2</D>',2)
go
insert into source_data values ('<D>A1</D><D>a2</D><D>b3</D>',3)
go
create table target(source nvarchar(max), i int, result nvarchar(max));
go
完整的 SQL fiddle 可在 http://sqlfiddle.com/#!18/d3e0da/1
在SQL 服务器中,我试图通过索引获取数组元素。 我通过将字符串转换为 XML 然后通过索引调用它来做到这一点。
SELECT CAST('<D>A1</D><D>a2</D>' AS XML).value('/D[1]','varchar(15)')
我的问题是我想在 '/D[1]'
中有一个数组索引作为输入参数。当我想将输入索引作为来自 table 的列时,这很有用,如下所示:
SELECT CAST('<D>A1</D><D>a2</D>' AS XML).value('/D['+COLUMN_WITH_INT_INDEX+']','varchar(15)') FROM TABLE_X
但是,这不起作用。我收到一条错误消息说
The argument 1 of the XML data type method "value" must be a string literal.
所有将 '/D['+COLUMN_WITH_INDEX+']'
转换为字符串文字的尝试都失败了。
您可以使用 sp_executesql 绕过“必须是文字”的约束,方法是将变量作为文字放入字符串中。
不过,您确实需要 运行 每个不同值的变体。
我在下面的示例中使用了两个过程。第一个处理索引的单个值并过滤掉索引不同或没有结果的任何记录。
create procedure proc_run_for_one (@i int) as
begin
declare @stmt nvarchar(max);
set @stmt = 'SELECT source, ' +
' cast(@i as nvarchar) + ',' +
' CAST(source AS XML).value(''/D['
+ cast(@i as nvarchar) + ']'',''varchar(15)'')
' FROM source_data '+
' WHERE i = ' + cast(@i as nvarchar) +
' AND CAST(source AS XML).value(''/D[' +
cast(@i as nvarchar) +
']'',''varchar(15)'') IS NOT NUll' ;
insert into target
exec sp_executesql @stmt;
end;
go
而第二个过程 运行 是每个值的第一个过程。我在这里使用了一个简单的计数器,但是 select distinct 可能会更有效,因为它只需要命中实际存在的值。
create procedure proc_run_for_all as
begin
declare @min int, @max int, @current int;
select @min = MIN(i), @max = MAX(i) FROM source_data;
set @current = @min;
while @current <= @max
begin
exec proc_run_for_one @current
set @current = @current + 1
end;
end;
go
表格和示例数据是
create table source_data (source nvarchar(max), i int)
go
insert into source_data values ('<D>A1</D><D>a2</D>',1)
go
insert into source_data values ('<D>A1</D><D>a2</D>',2)
go
insert into source_data values ('<D>A1</D><D>a2</D><D>b3</D>',3)
go
create table target(source nvarchar(max), i int, result nvarchar(max));
go
完整的 SQL fiddle 可在 http://sqlfiddle.com/#!18/d3e0da/1