自增長欄位值的連續遞增實現

来源:https://www.cnblogs.com/toomax/archive/2018/08/05/9426375.html
-Advertisement-
Play Games

一.背景 在上一篇《資料庫操作類SqlHelper》博文的最後,提到了一個實踐運用中遇到的問題,就是資料庫表中的自增長欄位的賦值不受人為控制。比如資料庫有一個tb_Department表,DeptNO欄位為自增長主鍵。 現在插入一行數據 啊!DeptNO欄位怎麼就是22了呢,不應該是從4開始嗎? 原 ...


背景

在上一篇《資料庫操作類SqlHelper》博文的最後,提到了一個實踐運用中遇到的問題,就是資料庫表中的自增長欄位的賦值不受人為控制。比如資料庫有一個tb_Department表,DeptNO欄位為自增長主鍵。

現在插入一行數據

啊!DeptNO欄位怎麼就是22了呢,不應該是從4開始嗎?

原因:這個表之前進行過很多插入操作,資料庫針對自增長欄位的每次插入都會自動+1,後來刪除了一部分行數據,然後重新插入的時候,資料庫不會依據表中缺失的欄位值進行賦值,而是在原先的基礎上繼續+1賦值。

結果:在新插入的“哈哈系”數據行之前,其實資料庫已經向表裡插入過21次了,只是DeptNO欄位值大於3的行數據被刪除了,現在要新插入行數據的話,就會在21的基礎上+1,也就是第二個表中出現的22了。

期望:

  1. 在插入新數據的時候,針對自增長欄位可以人為控制;
  2. 實際運用中,其實用戶並不知道數據表中自增長欄位缺失的是哪些值,程式需要自動提供缺失或者預設值。

設計

1.在插入新數據的時候,針對自增長欄位可以人為控制

資料庫中針對自增長欄位在插入時,不可以指定顯式值的。

insert into tb_Department(DeptNO,DeptName) values(4,N'嘿嘿系')

這樣插入數據會報錯的,提示你“當Identity_Insert設置為off時,不能為表’tb_Department’中的標識列插入顯式值”。很明顯,第一個期望的解決方案就是將Identity_Insert設置on,然後執行顯式值插入,最後關閉標識列插入開關。

set identity_insert tb_Department on
insert into tb_Department(DeptNO,DeptName) values(4,N'嘿嘿系')
set identity_insert tb_Department off

執行看看能不能插入,哇哦,成功了,棒棒噠。

2.實際運用中,用戶並不知道數據表中自增長欄位未使用有哪些值,程式需要自動提供缺失或者預設值

自增長欄位的值分為缺失值和預設值(這個術語是我自己定的,為了方便描述)

缺失值:比如數據表中自增長欄位的值為(1235),則缺失值為4要想讓程式自動檢索到缺失值,需要對數據表進行全面掃描,逐行判斷自增長欄位的值是否連續遞增,只要檢索到不連續的值就將對應序列的值返回,並顯示在窗體上,無需用戶自己輸入。

預設值:比如數據表中自增長欄位的值為(1234),則預設值為5。假設原先有10行數據,然後將大於4的行刪除後,自增長欄位本身還是連續遞增的,只需要找到預設值,返回給用戶。

利用SQL腳本創建存儲過程實現:(註意:該實現返回當前自增長欄位中第一個缺失值/預設值,只適用於每次插入一行數據的情況)

--創建一個存儲過程用於自動提取自增長欄位的第一個缺失值和預設值
create procedure NumOfDeptNOForInsert
@temp int output  --定義一個輸出參數,用於返回缺失值/預設值
as
declare @Count int   --定義一個當前表中的行數
select @Count=COUNT(1) from tb_Department   --給變數@Count賦值
declare @I int, @IsOK bit = 0,@num int = 1  --定義一個用於迴圈的@I變數,一個用於判斷是缺失值還是預設值的變數@IsOK,一個記錄預設值的變數@num
set @I = 1;   --變數@I賦值為1
while(@I <= @Count)   --開始迴圈掃描行數據
begin
    select @temp=DeptNO from tb_Department where DeptNO=@I   --檢索DeptNO值=@I值的行數據
    if(@temp != @I)  --判斷@I值與DeptNO值是否比對不成功
    begin
        set @temp = @I  --將@I值賦值給@temp
        set @IsOK = 0   --標記為缺失值
        break    --退出迴圈     
    end
    else    --判斷@I值與DeptNO值是否比對成功
    begin
        set @I = @I +1  --@I+1
        set @num = @I   --將@I賦值給@num
        set @IsOK = 1   --標記為預設值
    end 
end   

if(@IsOK =0)   --判斷是缺失值還是預設值,如果是缺失值
begin
    select @temp  --直接返回@temp
end
else    --如果是預設值
begin
    set @temp = @num  --將@num賦值給@temp
    select @temp      --再返回@temp
end

自增長欄位的連續遞增插入的存儲過程設計好後,首先在SQL Server中檢驗一下。

declare @temp int --定義輸出參數
exec dbo.NumOfDeptNOForInsert @temp  --調用儲存過程
print @temp  --列印輸出參數
  •  缺失值的檢驗:

             

調用存儲過程看看缺失的第一個值是不是5,結果跟預期一樣。

  • 預設值的檢驗:

           

調用存儲過程,找到的第一個預設值為7,結果跟預期的一樣。

 實踐

前面的分析設計做好後,當然就是運用於實踐了,主要是編寫獲取自增長欄位的缺失值/預設值的方法: 

        /// <summary>
        /// 獲取自增長欄位的第一個缺失值或者預設值
        /// </summary>
        /// <returns>缺失值/預設值</returns>
        private int GetDeptNO()
        {
            string cmdText = @"NumOfDeptNOForInsert";
            SqlParameter[] parameters =
            {
                new SqlParameter("@temp",SqlDbType.Int)
            };
            parameters[0].Direction = ParameterDirection.Output;
            int deptNO = (int)SqlHelper.ExecuteScalar(SqlHelper.ConnString, CommandType.StoredProcedure, cmdText,parameters);
            return deptNO;
        }

程式整體的UI設計和編碼在博文《資料庫操作類SqlHelper》中都已經講述,這裡就不在反覆講了。相對於之前來說,需要更改代碼的地方為“增加”按鈕的點擊處理程式和InsertData()方法: 

        private void tsbInsert_Click(object sender, EventArgs e)
        {
            cmdType = CmdType.Insert;
            //將gbDept控制項設置可用,textbox控制項設為可用,並將Text屬性清空
            this.gbDept.Enabled = true;
            this.txtDeptName.Enabled = true;
            this.txtDeptName.Text = string.Empty;
            //顯示即將插入的DeptNO值
            this.lbDeptNO.Text = GetDeptNO().ToString();
        }

        /// <summary>
        /// 插入數據
        /// </summary>
        private void InsertData()
        {
            //判斷系部名稱是否為空
            if (string.IsNullOrEmpty(this.txtDeptName.Text.Trim()))
            {
                MessageBox.Show("系部名稱不能為空!");
                return;
            }
            //定義插入數據的SQL腳本,其中set identity_insert tb_Department on/off主要是為了能讓自增長主鍵連續有序地插入
            string cmdText = @"set identity_insert tb_Department on 
                               insert into tb_Department(DeptNO,DeptName) values(@DeptNO,@DeptName)
                               set identity_insert tb_Department off";
            ////定義插入數據的Sql腳本
            //string cmdText = @"insert into tb_Department(DeptName) values(@DeptName)";
            //SQL腳本參數設置
            SqlParameter[] parameters =
            {
                new SqlParameter("@DeptNO",(object)this.lbDeptNO.Text),
                new SqlParameter("@DeptName",(object)this.txtDeptName.Text.Trim())
            };
            //執行插入,並返回受影響的行數
            int rows = SqlHelper.ExecuteNonQuery(SqlHelper.ConnString, CommandType.Text, cmdText, parameters);
            //判斷是否插入成功,並提示
            if (rows > 0)
            {
                //更新datagridview控制項的數據
                LoadData();
                //顯示即將插入的DeptNO值
                this.lbDeptNO.Text = GetDeptNO().ToString();
                //將系部名稱設為空
                this.txtDeptName.Text = string.Empty;
                MessageBox.Show("插入成功!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            else
            {
                MessageBox.Show("插入失敗!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
        }

        private void btnOK_Click(object sender, EventArgs e)
        {
            //執行增刪改操作
            switch (cmdType)
            {
                case CmdType.Insert:
                    InsertData();
                    break;
                case CmdType.Delete:
                    DeleteData();
                    break;
                case CmdType.Update:
                    UpdateData();
                    break;
            }
        }

結果

UI和編碼完成後,調試程式是很關鍵的,能從調試的過程中重現整個功能的思路,也能找到一些問題所在,修複bug,然後重編碼。廢話不多說看結果吧:

1.缺失值:

假設一開始的tb_Department表如下圖所示,理論上缺失的值為(457),現在往表裡插入新值,看看結果如何。點擊“增加”按鈕,窗體下方系部編號自動出現第一個缺失值4,系部名稱我們設置為“嘟嘟系”,提交添加成功後,系部編號會自動顯示下一個缺失值5。為了後面的預設值的結果,我們再增加缺失值(57)兩行數據,使DeptNO欄位連續遞增。

 

2.預設值:

DeptNO欄位連續遞增時,如下圖所示,點擊“增減”按鈕,窗體下方的系部編號成功地提取到第一個預設值9,系部名稱輸入“物理系”,提交增加成功後,系部編號會自動顯示下一個預設值10

 

調試結果顯示我們提出的需求已經得到解決。

一.總結

本文主要針對數據表中自增長欄位的插入問題進行講解,不管表中的數據增刪過多少次,程式總是能提供自增長欄位的缺失值或者預設值用於新數據行的插入,從而實現插入自增長欄位值的連續遞增特性。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、版本說明 1.1、MySQL相關連接 MySQL官網:https://www.mysql.com/ MySQL下載:https://dev.mysql.com/downloads/mirrors/ MySQL文檔:https://dev.mysql.com/doc/relnotes/mysql/... ...
  • 資料庫編程 從前面我們知道資料庫概念包含 資料庫文件、伺服器和資料庫客戶端 客戶端我們之前已經用過的有navicat/mysql-client等程式。 問題: 如何使用客戶端將100000行數據插入到資料庫? 大家會發現如果用之前客戶端幾乎是不可能完全這個任務的, 因為我們不可能去構造出那個插入10 ...
  • 該文章是基於 Hadoop2.7.6_01_部署 、 Hive-1.2.1_01_安裝部署 進行的 1. 前言 在一個完整的大數據處理系統中,除了hdfs+mapreduce+hive組成分析系統的核心之外,還需要數據採集、結果數據導出、任務調度等不可或缺的輔助系統,而這些輔助工具在hadoop生態 ...
  • 占座 ...
  • 1197多語句事務要求更大的max_binlog_cache_size報錯 binlog_cache_size:為每個session 分配的記憶體,在事務過程中用來存儲二進位日誌的緩存,提高記錄bin-log的效率。沒有什麼大事務,dml也不是很頻繁的情況下可以設置小一點,如果事務大而且多,dml操作 ...
  • sqlServer_基礎概念 SQL server的管理工具 SQL server聯機叢書 開始菜單à Microsoft SQL Server 2008 à 文檔和教程 à SQL Server聯機叢書 SQL Server 配置管理器 用於啟動和管理SQL server資料庫的服務端,以及其他相 ...
  • mysql資料庫基礎知識 什麼是資料庫 資料庫顧名思義,就是用來存儲數據的工具,用一個比例形象的例子來比喻,就是Excel,一個Excel文件就可以看成是一個資料庫。 關係型資料庫 就是以行與列構成的二維數據表的形式,用來存儲數據的,並且將多張數據表存儲在一個單元中的存儲形式,就稱為關係型資料庫。 ...
  • Oracle Drop表並未直接刪除 drop table xx purge drop表 執行drop table xx 語句 drop後的表被放在回收站(user_recyclebin)里,而不是直接刪除掉。這樣,回收站里的表信息就可以被恢復,或徹底清除。 通過查詢回收站user_recycleb ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...