簡體   English   中英

如何獲取大於多列值的值,而不是使用SQL Server中的復合鍵字段

[英]How to get value greater than multiple columns value rather than using composite key field from SQL Server

如果我有包含以下數據的表:

分支,類型,數字=>這將生成復合鍵字符串'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;

如果您嘗試獲取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;

我建議您使用“數學”:將列按“相關順序”放置,然后相乘以在單個字段中容納所有數字。 例如: 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)

我建議您添加數據庫觸發器以強制執行這些最大長度

在數據庫中創建此功能

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位數字時。

到目前為止,所有答案都使用非常基礎的數學。 如果您不懂基本的數學知識,您將無法像一名程序員那樣步履維艱,因此您應該優先考慮提高該技能。

您在對其他答案的評論中說過,您不想填充DataSet或使用MoveNext等。另一種方法是創建一個包含復合鍵的視圖。

首先,創建我在其他答案中定義的函數

然后,創建視圖

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

這種方法可能會比我的其他答案提高查詢性能。 您需要對其進行測試才能找到答案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM