Microsoft SQL Server 如何實(shí)現(xiàn)一個(gè)只有一行數(shù)據(jù)的表
作者: 不剪發(fā)的Tony老師
畢業(yè)于北京航空航天大學(xué),十多年數(shù)據(jù)庫管理與開發(fā)經(jīng)驗(yàn),目前在一家全球性的金融公司從事數(shù)據(jù)庫架構(gòu)設(shè)計(jì)。CSDN學(xué)院簽約講師以及GitChat專欄作者。csdn上的博客收藏于以下地址:https://tonydong.blog.csdn.net
文章目錄
基于計(jì)算列的唯一約束
使用 MERGE 插入和更新
通過觸發(fā)器禁止刪除數(shù)據(jù)
總結(jié)
大家好,我是只談技術(shù)不剪發(fā)的 Tony 老師。今天我們繼續(xù)討論如何在 Microsoft SQL Server 中實(shí)現(xiàn)一個(gè)只能存儲(chǔ)一行數(shù)據(jù)的表。
??如果你使用的是 MySQL,可以通過這篇文章了解如何在 MySQL 中實(shí)現(xiàn)一個(gè)只有一行數(shù)據(jù)的表。
??如果你使用的是 Oracle,可以通過這篇文章了解如何在 Oracle 中實(shí)現(xiàn)一個(gè)只有一行數(shù)據(jù)的表。
??如果你使用的是 PostgreSQL,可以通過這篇文章了解如何在 PostgreSQL 中實(shí)現(xiàn)一個(gè)只有一行數(shù)據(jù)的表。
假如我們的系統(tǒng)有一個(gè)配置表,存儲(chǔ)了系統(tǒng)名稱、版本等信息,例如:
create table configuration(
system_name varchar(100) not null,
system_version varchar(50) not null,
update_date datetime2 not null
);
現(xiàn)在要求在第一次部署應(yīng)用程序時(shí)在表中生成一條記錄,以后升級(jí)應(yīng)用時(shí)更新配置信息,同時(shí)需要防止用戶誤刪除該記錄。
基于計(jì)算列的唯一約束
Microsoft SQL Server 支持計(jì)算列(Computed Column),可以基于其他字段計(jì)算得到該列的值。當(dāng)計(jì)算列基于確定性的表達(dá)式時(shí),可以用于創(chuàng)建索引(類似于函數(shù)索引)。因此,我們可以創(chuàng)建一個(gè)基于常量的計(jì)算列,并且創(chuàng)建一個(gè)主鍵或者唯一約束。例如:
alter table configuration add only_one_row as (1);
alter table configuration add constraint configuration_un unique (only_one_row);
計(jì)算列 only_one_row 的值永遠(yuǎn)等于 1,再加上一個(gè)唯一性約束,意味著表中最多只能存儲(chǔ)一行數(shù)據(jù)。
使用 MERGE 插入和更新
在第一次部署應(yīng)用程序時(shí),可以執(zhí)行以下 INSERT 語句插入一條數(shù)據(jù):
insert into configuration(system_name, system_version, update_date)
values ('ERP 系統(tǒng)', '版本: 2020.01', current_timestamp);
select * from configuration;
system_name|system_version|update_date |only_one_row|
-----------|--------------|-------------------|------------|
ERP 系統(tǒng) |版本: 2020.01 |2020-07-23 07:22:54| 1|
如果在升級(jí)應(yīng)用程序時(shí)繼續(xù)插入數(shù)據(jù)就會(huì)返回錯(cuò)誤:
insert into configuration(system_name, system_version, update_date)
values ('ERP 系統(tǒng)', '版本: 2020.02', current_timestamp);
SQL Error [2627] [23000]: Violation of UNIQUE KEY constraint 'configuration_un'. Cannot insert duplicate key in object 'dbo.configuration'. The duplicate key value is (1).
為了避免唯一約束沖突,我們需要在執(zhí)行插入語句之前查詢一次數(shù)據(jù)。如果沒有結(jié)果就插入記錄,否則需要更新記錄。
update configuration
set system_name = 'ERP 系統(tǒng)',
system_version = '版本: 2020.02',
update_date = current_timestamp;
select * from configuration;
system_name|system_version|update_date |only_one_row|
-----------|--------------|-------------------|------------|
ERP 系統(tǒng) |版本: 2020.02 |2020-07-23 07:33:12| 1|
一個(gè)更簡(jiǎn)單的方法就是使用 MERGE 語句,它可以同時(shí)實(shí)現(xiàn) INSERT、UPDATE 和 DELETE 語句的功能。我們使用 MERGE 語句將上面的操作修改如下:
-- 清除數(shù)據(jù)
truncate table configuration;
merge into configuration t
using (select 'ERP 系統(tǒng)' system_name, '版本: 2020.01' system_version, current_timestamp update_date) s
on (1=1)
when matched then
update set t.system_name = s.system_name,
t.system_version = s.system_version,
t.update_date = s.update_date
when not matched then
insert (system_name, system_version, update_date)
values (s.system_name, s.system_version, s.update_date);
system_name|system_version|update_date |only_one_row|
-----------|--------------|-------------------|------------|
ERP 系統(tǒng) |版本: 2020.01 |2020-07-23 07:46:20| 1|
MERGE 語句使用 1=1 作為數(shù)據(jù)沖突的判斷條件,如果表已經(jīng)存在任何數(shù)據(jù)則更新,如果不存在則插入數(shù)據(jù)。
通過觸發(fā)器禁止刪除數(shù)據(jù)
解決了數(shù)據(jù)的插入和更新問題,還需要防止用戶誤刪除配置表中的信息。這個(gè)需求可以通過觸發(fā)器來實(shí)現(xiàn),首先創(chuàng)建一個(gè)觸發(fā)器:
create or alter trigger tri_disable_configuration_del
on configuration
instead of delete
as
begin
raiserror ('禁止刪除版本信息!', 18, 1);
end
tri_disable_configuration_del 是一個(gè) INSTEAD OF 觸發(fā)器,替代了刪除操作并返回一個(gè)錯(cuò)誤信息。
執(zhí)行以下語句刪除配置數(shù)據(jù):
delete from configuration
where only_one_row = 1;
SQL Error [50000] [S0001]: 禁止刪除版本信息!
system_name|system_version|update_date |only_one_row|
-----------|--------------|-------------------|------------|
ERP 系統(tǒng) |版本: 2020.02 |2020-07-23 07:51:10| 1|
以上刪除語句返回了錯(cuò)誤信息,t_version 中的數(shù)據(jù)仍然存在。
需要注意的是,TRUNCATE TABLE 語句仍然可以清除表中的數(shù)據(jù),因?yàn)樗粫?huì)觸發(fā) DML 觸發(fā)器。
總結(jié)
為了在 Microsoft SQL Server 中為了實(shí)現(xiàn)一個(gè)只有一行數(shù)據(jù)的表,可以創(chuàng)建一個(gè)數(shù)值為常量的計(jì)算列,并且基于該字段創(chuàng)建唯一索引。使用 MERGE 語句實(shí)現(xiàn)插入和更新操作;同時(shí)為了防止數(shù)據(jù)被刪除,可以通過觸發(fā)器禁止刪除操作。
除了本文使用的方法之外,你還有沒有其他的實(shí)現(xiàn)方法?歡迎關(guān)注??、評(píng)論??、點(diǎn)贊??