【发布时间】:2019-09-04 16:27:02
【问题描述】:
我有一个存储过程,它需要假设行顺序始终相同才能正常运行,否则我会得到不正确的数据。用户提供需要查询的 ID 字符串,存储过程使用 STRING_SPLIT(@Parameter, ',') 操作将此字符串放入表中。
假设字符串将按照它们在表中的顺序放入表中是否安全?我创建了一个单元测试并运行了 10000 次,每次检查表的顺序并通过。因此,我猜测做出这个假设是安全的。
SQL:
CREATE PROCEDURE [dbo].[sp_TestOrder] @TestIDs varchar(5000)
AS
IF(OBJECT_ID('tempdb..#TestNames') IS NOT NULL) BEGIN DROP TABLE #TestNames END
-- INTO #FundNames
SELECT RTRIM(LTRIM(value)) AS TestIDs
INTO #TestNames
FROM string_split(@TestIDs, ',');
ALTER TABLE #TestNames ADD RowNumber INT IDENTITY(1,1)
SELECT * FROM #TestNames
IF(OBJECT_ID('tempdb..#TestNames') IS NOT NULL) BEGIN DROP TABLE #TestNames END
GO
C# 中的单元测试
[TestMethod]
public void SQLOrderTest()
{
// Arrange
string testIds = "3, 5, 1, 10";
string spName = "[dbo].[sp_TestOrder]";
string ServerName = PARR_DBDataObject.ServerName;
string DBName = PARR_DBDataObject.DBName;
// Act
bool results = true;
for(int i = 0; i < 10000; i++)
{
DataTable dt = SQL.QueryStoredProcedure(spName, DBName, ServerName, false, 5000,
new Tuple<string, object>("@TestIDs", testIds));
// First Row
if (GetRowNumber(dt, "3") != 1) results = false;
// Second Row
if (GetRowNumber(dt, "5") != 2) results = false;
// Third Row
if (GetRowNumber(dt, "1") != 3) results = false;
// Forth Row
if (GetRowNumber(dt, "10") != 4) results = false;
}
Assert.AreEqual(results, true);
}
private int GetRowNumber(DataTable dt, string TestIDValue)
{
var row = from r in dt.AsEnumerable()
where r.Field<string>("TestIDs") == TestIDValue
select new
{
TestID = r.Field<string>("TestIDs"),
rowNum = r.Field<Int32>("RowNumber")
};
return row.First().rowNum;
}
【问题讨论】:
-
SQL Server 是多线程的,数据是随机保存和读取的。始终以相同顺序获取数据的唯一方法是使用 ORDER BY。如果您需要按特定顺序检索数据而不是添加带有序列号的列。
标签: c# sql stored-procedures ssms