表值参数的排序顺序是否保证保持不变?

时间:2016-09-13 10:01:14

标签: c# sql-server ado.net sql-server-2014 table-valued-parameters

我需要知道是否需要在我的自定义表类型中添加一个排序列,然后我可以使用它来排序,或者如果我可以相信即使没有这样的列,参数的顺序也保持不变。

这是我的类型:

CREATE TYPE [dbo].[VwdCodeList] AS TABLE(
    [VwdCode] [varchar](50) NOT NULL
)

这是一个使用它的sql:

/// <summary>
///     Inserts all new WatchListCodes for a given watchlist
/// </summary>
public const string InsertWatchListCodes = @"
INSERT INTO [dbo].[WatchListCodes]
   ([WatchListID]
   ,[VwdCode]
   ,[Sort])
 SELECT @WatchListID, VwdCode, ROW_NUMBER()OVER(ORDER BY (SELECT 1)) 
 FROM @VwdCodeList;";

正如您所看到的,我使用ROW_NUMBER来获取排序列值。

我是否还需要在表类型中添加排序列,还是保证(记录)它保持不变?它似乎有效。

这是我使用它的ADO.NET代码:

SqlParameter vwdCodeListParameter = insertWatchListCodeCommand.Parameters.Add("@VwdCodeList", SqlDbType.Structured);
vwdCodeListParameter.TypeName = "[dbo].[VwdCodeList]";
vwdCodeListParameter.Value = WatchListSql.GetVwdCodeRecords(newVwdCodes, true);
int inserted = insertWatchListCodeCommand.ExecuteNonQuery();

GetVwdCodeRecords会为IEnumerable<SqlDataRecord>返回IEnumerable<string>

谢谢大家。如果未来的读者有兴趣知道我如何保证排序顺序。我通过添加另一列来修改表格类型:

CREATE TYPE [dbo].[VwdCodeList] AS TABLE(
    [VwdCode] [varchar](50) NOT NULL,
    [Sort] [smallint] NOT NULL
)

insert-sql甚至更简单,因为sort-column是传入的而不是计算的:

public const string InsertWatchListCodes = @"
INSERT INTO [dbo].[WatchListCodes]
   ([WatchListID]
   ,[VwdCode]
   ,[Sort])
 SELECT @WatchListID, cl.VwdCode, cl.Sort 
 FROM @VwdCodeList cl;";

为了完整起见,这里是返回用作table-valued-parameter的值的IEnumerable<SqlDataRecord>的方法(省略错误处理):

public static IEnumerable<SqlDataRecord> GetVwdCodeRecords(IEnumerable<string> vwdCodes, bool trimCode = true)
{
    short currentSort = 0;
    foreach (string vwdCode in vwdCodes)
    {
        var record = new SqlDataRecord(
            new SqlMetaData("VwdCode", SqlDbType.VarChar, 50), 
            new SqlMetaData("Sort", SqlDbType.SmallInt));
        record.SetString(0, trimCode ? vwdCode.Trim() : vwdCode);
        record.SetInt16(1, ++currentSort);

        yield return record;
    }
}

3 个答案:

答案 0 :(得分:3)

一般情况下:任何结果集都没有隐式排序顺序

实现保证排序顺序唯一方式是最外层查询的 ORDER BY

我确定你已经知道了......

有一个specialty with ROW_NUMBER() OVER(ORDER BY ...) Read "General Remarks"。但这很危险。

  • 如果您在ORDER BY中使用唯一排序标准,则排序顺序才有意义。您正在使用SELECT 1,这不保证任何排序顺序。这可能会进行数百次测试并突然中断......
  • 任何后续操作都可以破坏此排序顺序。只是想象你有一个工作函数 - 几个月后 - 你在一个复杂的查询中使用这个函数。

我使用它来创建具有确定顺序的XML,因为在XML中有一个由位置给出的隐式顺序...

答案 1 :(得分:1)

是的,您需要添加一列。 SQL是一种基于集合的语言,并且集合本身就是无序的(不可否认,在这种情况下,SQL存在一些漏洞)。

如果您想使用ORDER BY并希望保证结果,则需要确保它基于表格中基于数据的足够表达式,例如它唯一地定义了排序。在这里,您通过常量进行排序(如果您只是尝试ORDER BY 1,则会收到警告,这应该足以证明它不能正常工作)因此无法保证实际应用的排序

答案 2 :(得分:1)

除非您通过..

执行明确的订单,否则无法保证相同的顺序

以下是一些测试..

 create type numbes as table
 (
 num int primary key
 )


 DECLARE @nums AS numbes;  

 insert into @nums
 select row_number() over(order by(select 1)) 
 from
 master.sys.objects


 select Top 100* from @nums 

和执行计划显示..

enter image description here

下面的代码......

ROW_NUMBER()OVER(ORDER BY (SELECT 1)) 
 FROM @VwdCodeList;";
除非您通过

提及明确的订单,否则

每次都可能无法获得相同的订单