如果我的表包含以下数据:
分支,类型,数字=>这将生成复合键字符串'keyfield'
分支的长度,类型为[int] [4]
数字的长度是[int] [7]
数据是这样的:
branch, type, number
13, 1309, 1 row1
13, 1309, 2 row2
13, 1310, 1 row3
14, 1309, 1 row4
所以我有keyfield->称为'KeyField'列,但是idont需要使用它,它可以工作,但是我只需要使用表达式而不是字符串keyfield
例如:
如果我需要使行大于上面的row2:
我写道:
SELECT TOP 1 * FROM TABLE WHERE KeyField > '0013130900002'
->我不喜欢使用字符串作为复合键..
我也不能像这样手动创建它:
SELECT TOP 1 * FROM TABLE WHERE brn > 1 AND type > 1309 and num > 2
这行不通...所以我只需要通过表达式获取下一行
例如:getGreatRow(1,1309,2); //这将返回row3我需要做的。 这样该功能可以直接与C#和屏幕上的文本框一起使用! 我需要选择唯一的前1个记录,该记录大于我指定的当前记录或表达式的值。
修改
我根据需要使用Gordon SQL生成带有主键列表的C#。感谢戈登。
在C#中自动生成SQL查询:
public List<EntryTable> Tables { get; private set; }
public List<BufferElement> Buffer { get; private set; }
string Query = string.Empty;
for (int i = 0; i < Tables[0].PrimaryKeys.Count; i++)
{
Query += "(";
for (int j = 0; j < i; j++)
{
switch (Tables[0].PrimaryKeys[j].CLRType)
{
case CLRType.CLR_BYTE:
Query += $"{Tables[0].PrimaryKeys[j].KeyPart} = {Convert.ToByte(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[j].KeyPart).Value)} AND ";
break;
case CLRType.CLR_INT16:
Query += $"{Tables[0].PrimaryKeys[j].KeyPart} = {Convert.ToInt16(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[j].KeyPart).Value)} AND ";
break;
case CLRType.CLR_INT32:
Query += $"{Tables[0].PrimaryKeys[j].KeyPart} = {Convert.ToInt32(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[j].KeyPart).Value)} AND ";
break;
case CLRType.CLR_INT64:
Query += $"{Tables[0].PrimaryKeys[j].KeyPart} = {Convert.ToInt64(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[j].KeyPart).Value)} AND ";
break;
case CLRType.CLR_SINGLE:
Query += $"{Tables[0].PrimaryKeys[j].KeyPart} = {Convert.ToSingle(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[j].KeyPart).Value)} AND ";
break;
case CLRType.CLR_DOUBLE:
Query += $"{Tables[0].PrimaryKeys[j].KeyPart} = {Convert.ToDouble(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[j].KeyPart).Value)} AND ";
break;
case CLRType.CLR_DECIMAL:
Query += $"{Tables[0].PrimaryKeys[j].KeyPart} = {Convert.ToDecimal(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[j].KeyPart).Value)} AND ";
break;
case CLRType.CLR_Boolean:
Query += $"{Tables[0].PrimaryKeys[j].KeyPart} = {Convert.ToBoolean(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[j].KeyPart).Value)} AND ";
break;
case CLRType.CLR_STRING:
Query += $"{Tables[0].PrimaryKeys[j].KeyPart} = '{Convert.ToString(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[j].KeyPart).Value)}' AND ";
break;
case CLRType.CLR_DATETIME:
Query += $"{Tables[0].PrimaryKeys[j].KeyPart} = '{Convert.ToDateTime(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[j].KeyPart).Value)}' AND ";
break;
case CLRType.CLR_TIME:
Query += $"{Tables[0].PrimaryKeys[j].KeyPart} = '{TimeSpan.Parse(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[j].KeyPart).Value)}' AND ";
break;
}
}
switch (Tables[0].PrimaryKeys[i].CLRType)
{
case CLRType.CLR_BYTE:
Query += $"{Tables[0].PrimaryKeys[i].KeyPart} > {Convert.ToByte(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[i].KeyPart).Value)}";
break;
case CLRType.CLR_INT16:
Query += $"{Tables[0].PrimaryKeys[i].KeyPart} > {Convert.ToInt16(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[i].KeyPart).Value)}";
break;
case CLRType.CLR_INT32:
Query += $"{Tables[0].PrimaryKeys[i].KeyPart} > {Convert.ToInt32(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[i].KeyPart).Value)}";
break;
case CLRType.CLR_INT64:
Query += $"{Tables[0].PrimaryKeys[i].KeyPart} > {Convert.ToInt64(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[i].KeyPart).Value)}";
break;
case CLRType.CLR_SINGLE:
Query += $"{Tables[0].PrimaryKeys[i].KeyPart} > {Convert.ToSingle(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[i].KeyPart).Value)}";
break;
case CLRType.CLR_DOUBLE:
Query += $"{Tables[0].PrimaryKeys[i].KeyPart} > {Convert.ToDouble(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[i].KeyPart).Value)}";
break;
case CLRType.CLR_DECIMAL:
Query += $"{Tables[0].PrimaryKeys[i].KeyPart} > {Convert.ToDecimal(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[i].KeyPart).Value)}";
break;
case CLRType.CLR_Boolean:
Query += $"{Tables[0].PrimaryKeys[i].KeyPart} > {Convert.ToBoolean(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[i].KeyPart).Value)}";
break;
case CLRType.CLR_STRING:
Query += $"{Tables[0].PrimaryKeys[i].KeyPart} > '{Convert.ToString(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[i].KeyPart).Value)}'";
break;
case CLRType.CLR_DATETIME:
Query += $"{Tables[0].PrimaryKeys[i].KeyPart} > '{Convert.ToDateTime(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[i].KeyPart).Value)}'";
break;
case CLRType.CLR_TIME:
Query += $"{Tables[0].PrimaryKeys[i].KeyPart} > '{TimeSpan.Parse(Buffer.Find(x => x.ID == Tables[0].PrimaryKeys[i].KeyPart).Value)}'";
break;
}
Query += $") {(Tables[0].PrimaryKeys.Count > 1 && i != Tables[0].PrimaryKeys.Count - 1 ? " OR " : string.Empty)} \n";
}
Query += $"ORDER BY {string.Join(" ASC, ", Tables[0].PrimaryKeys.Select(x => x.KeyPart).ToArray())} ASC";
SelectCommand = $"SELECT TOP 1 * FROM {Tables[0].Table} WHERE " + Query;
答案 0 :(得分:0)
如果您尝试获取1, 1309, 2
之后的下一行
SELECT TOP 1 *
FROM TABLE
WHERE brn > 1 OR
(brn = 1 AND type > 1309) OR
(brn = 1 AND type = 1309 AND num > 2)
ORDER BY brn DESC, type DESC, num DESC;
答案 1 :(得分:0)
我建议您使用“数学”:将列按“相关顺序”放置,然后相乘以在单个字段中容纳所有数字。例如:
new_id=first_column*100000+second_column*10+third_column
因此,在第1行的情况下,您将获得1313091作为代码。数学比字符串处理要快得多。然后,您将能够查询将密钥除以所需的部分。最终在您认为会增长很多的列上添加更多零。
当您使用列构建键以保持外部顺序时,顺序会保留。
因此您的查询将类似于:
select *
from table
where new_id > (branch)*100000+(type)*10+number
IDEA是这样的:
123456 99349199 12341234 : having enough space for a 'reasonable' amount of numbers
000000 00000000 00000000
so 123456 x 1 00000000 00000000 = 123456 00000000 00000000 +
99349199 x 1 00000000 = 99349199 00000000 +
and
12341234 x 1 = 12341234 =
-------------------------
123456 99349199 12341234
已更新:
select *
from my_table
WHERE new_id (branch)*1 00000000 00000000+(type)*1 00000000+number
显然我们的“ new_label”定义已更改:
new_label= (branch)*100000000 00000000+(type)*100000000 + number
因此您可以拥有以下最大长度:
<all digits you want> (branch) + 8 digit (type) + 8 digit (number)
我建议您添加数据库触发器以强制执行这些最大限制
答案 2 :(得分:0)
在数据库中创建此功能
CREATE FUNCTION dbo.GetCompositeKey(@branch int, @type int, @number int)
RETURNS bigint
AS
BEGIN
RETURN cast(@branch as bigint) * 100000000000 + cast(@type as bigint) * 10000000 + @number
END
,然后在进行比较时使用它,如下所示:
SELECT TOP 1 * FROM [TABLE]
WHERE dbo.GetCompositeKey(branch, type, number) >
dbo.GetCompositeKey(13, 1309, 2)
ORDER BY dbo.GetCompositeKey(branch, type, number)
注意:为简化说明,此查询经过简化。从C#执行时,应使用参数化查询为SQL函数提供3个整数,以避免SQL注入攻击。
编辑:发布此内容后,我读了一些其他答案的评论,其中您说您不懂数学。到目前为止,在大多数答案中,方法只是创建一个将所有三个值(分支,类型和数字)组合在一起以创建可比较值的大整数。实际上,这与在您的问题('0013130900002')中使用字符串连接和基于字符串的复合键的操作相同。正如另一个答案中指出的那样,数学方法应该更快。字符串中的另一个错误是将@number字段仅零填充为5位数字,当您已经声明它必须能够容纳7位数字时。
可以肯定的是,到目前为止,所有答案都使用非常基础的数学。如果您不懂基本的数学知识,您将无法像一名程序员那样步履维艰,因此您应该优先考虑提高该技能。
答案 3 :(得分:0)
您在对其他答案的评论中说,您不想填充数据集或使用MoveNext等。另一种方法是创建一个包含复合键的视图。
首先,创建我在my other answer中定义的函数
然后,创建视图
CREATE VIEW [myview]
AS
SELECT
*,
dbo.GetCompositeKey(branch, type, number) as CompositeKey
FROM [table]
像这样查询它:
SELECT TOP 1 * FROM [myview]
WHERE CompositeKey > dbo.GetCompositeKey(13, 1309, 2)
ORDER BY CompositeKey
这种方法可能会比我的其他答案提高查询性能。您需要对其进行测试才能找到答案。