所以我试图使用游标将一些xml插入到我的SQL数据库中,我想将一个'order by'语句放入游标声明中,否则优化器决定将所有节点按字母顺序排列。
我的光标声明是:
declare cur1 cursor local for
select
P.DescriptionId, N.Description
from (
select
T.C.value('.', 'nvarchar(max)') as Description
from @TheRole.nodes('/descriptions/description') as T(C)
) as N
left outer join PositionsDescriptions as P on N.Description = P.Description
我试图插入:
order BY P.$IDENTITY
根据要求 - 这是整个SP:
@Title nvarchar(50),
@Location nvarchar(50),
@ShortDescription nvarchar(max),
@MaximumSalary nvarchar(max) = null,
@StatusId int,
@DepartmentId int,
@SubDepartmentId int = null,
@TheRole xml = null,
@Essentials xml = null,
@Desirable xml = null
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE @PositionId as int
--DESCRIPTION TABLES
DECLARE @TableRole TABLE(Description nvarchar(MAX), OrderNumber int)
--DECLARE @TableRole TABLE(RowID int not null primary key identity(1,1), Description nvarchar(MAX), OrderNumber int)
DECLARE @TableEssentials TABLE(RowID int not null primary key identity(1,1), Description nvarchar(MAX), OrderNumber int)
DECLARE @TableDesirable TABLE(RowID int not null primary key identity(1,1), Description nvarchar(MAX), OrderNumber int)
DECLARE @RowsToProcess int,
@CurrentRow int,
@Description nvarchar(MAX),
@OrderNumber int,
--DESCRIPTIONS
@DescriptionId int
set @OrderNumber = 1
-- POSITIONS
if @SubDepartmentId = 0
SET @SubDepartmentId = NULL
INSERT INTO Positions (Title, Location, Description, MaximumSalary, StatusId, SubDepartmentId, DepartmentId, Published, LastUpdatedDate)
VALUES (@Title, @Location, @ShortDescription, @MaximumSalary,@StatusId, @SubDepartmentId, @DepartmentId, GETDATE(), GETDATE())
SET @PositionId = scope_identity()
-- POSITIONSDESCRIPTIONS AND POSITIONS_DESCRIPTIONS
-- TheRole
declare cur1 cursor local for
select
P.DescriptionId, N.Description
from (
select
T.C.value('.', 'nvarchar(max)') as Description
from @TheRole.nodes('/descriptions/description') as T(C)
) as N
left outer join PositionsDescriptions as P on N.Description = P.Description
open cur1
while 1 = 1
begin
fetch cur1 into @DescriptionId, @Description
if @@fetch_status <> 0 break
if @DescriptionId is null
begin
insert into PositionsDescriptions (Description)
select @Description
select @DescriptionId = scope_identity()
end
insert INTO Positions_Descriptions(PositionId, SectionId, DescriptionId, OrderNumber)
VALUES (@PositionId, 1, @DescriptionId, @OrderNumber)
set @OrderNumber = @OrderNumber + 1
end
close cur1
deallocate cur1
-- Essentials
declare cur1 cursor local fast_forward for
select
P.DescriptionId, N.Description
from (
select
T.C.value('.', 'nvarchar(max)') as Description
from @Essentials.nodes('/descriptions/description') as T(C)
) as N
left outer join PositionsDescriptions as P on P.Description = N.Description
open cur1
while 1 = 1
begin
fetch cur1 into @DescriptionId, @Description
if @@fetch_status <> 0 break
if @DescriptionId is null
begin
insert into PositionsDescriptions (Description)
select @Description
select @DescriptionId = scope_identity()
end
insert INTO Positions_Descriptions(PositionId, SectionId, DescriptionId, OrderNumber)
VALUES (@PositionId, 2, @DescriptionId, @OrderNumber)
set @OrderNumber = @OrderNumber + 1
end
close cur1
deallocate cur1
-- Desirable
declare cur1 cursor local fast_forward for
select
P.DescriptionId, N.Description
from (
select
T.C.value('.', 'nvarchar(max)') as Description
from @Desirable.nodes('/descriptions/description') as T(C)
) as N
left outer join PositionsDescriptions as P on P.Description = N.Description
Declare @DesirablesOrderNumber int = 1
open cur1
while 1 = 1
begin
fetch cur1 into @DescriptionId, @Description
if @@fetch_status <> 0 break
if @DescriptionId is null
begin
insert into PositionsDescriptions (Description)
select @Description
select @DescriptionId = scope_identity()
end
insert INTO Positions_Descriptions(PositionId, SectionId, DescriptionId, OrderNumber)
VALUES (@PositionId, 3, @DescriptionId, @OrderNumber)
set @OrderNumber = @OrderNumber + 1
end
close cur1
deallocate cur1
END
如果有比光标更好的方法,我很想知道!这是我正在尝试解决的其他人的代码,我是SQL的新手,所以如果我有点慢,请道歉。
有关详细信息,请参阅上面提到的表格PositionsDescriptions和Positions_Descriptions。
PositionsDescriptions看起来像这样:
DescriptionId Description
1 test
2 abc
此数据与名为Positions_Descriptions的表中的作业(或位置)相关,如下所示:
PositionId SectionId DescriptionId OrderNumber
1 1 1 1
1 1 2 2
问题在于,如果你有(例如)这样的事情:
@TheRole = "<descriptions><description>test</description><description>abc</description></descriptions>"
然后信息不按该顺序存储。但存储以便描述按字母顺序返回。
换句话说,你得到了这个
PositionId SectionId DescriptionId OrderNumber
1 1 2 1
1 1 1 2
而不是这个:
PositionId SectionId DescriptionId OrderNumber
1 1 1 1
1 1 2 2
答案 0 :(得分:1)
如果没有order by子句,您的行可以以优化程序认为合适的任何方式返回。
在您的情况下,这意味着列OrderNumber
可能与XML中元素的顺序不匹配。
使用nodes()
命令row_number()
提取的XML元素有一个技巧。有关详细信息,请参阅Does the nodes()
method keep the document order?。
使用此游标定义,您的行将按照它们存储在XML中的顺序进行处理。
declare cur1 cursor local for
select
P.DescriptionId, N.Description
from (
select
T.C.value('.', 'nvarchar(max)') as Description,
row_number() over(order by T.C) as rn
from @TheRole.nodes('/descriptions/description') as T(C)
) as N
left outer join PositionsDescriptions as P on N.Description = P.Description
order by N.rn
答案 1 :(得分:1)
Mikael Eriksson已经介绍了订购问题。您可以在不必使用Cusror的情况下插入表(不包括任何重复项)的方法是向INSERT..SELECT添加WHERE EXISTS子句,以过滤掉已存在的那些子句。
像这样:
INSERT INTO PositionsDescriptions( Description )
SELECT T.C.value('.', 'nvarchar(max)')
FROM @TheRole.nodes('/descriptions/description') as T(C)
WHERE NOT EXISTS
(
SELECT * From PositionsDescriptions N
WHERE T.C.value('.', 'nvarchar(max)') = N.Description
)
如果您需要防止同一来源中的重复项,您可以将DISTINCT添加到外部SELECT。