【SqlServer】計算列(Computed Columns)使用案例


Sql Server提供的計算列是一個虛擬的列,通常情況下該列的值是由表中的其它列計算得出的。默認情況下,它不占用磁盤容量,因為這些計算列都是根據指定的表達式動態計算出來的,只有查詢的時候才會進行計算出來。然而,如果使用了persisted關鍵字的計算列,該關鍵詞會將表達式的計算結果寫入到磁盤中,並進行持久化存儲。同時,也可以在計算列上建立索引,約束,或外鍵等。

 

場景舉例:

a. 提高JSON數據查詢的效率。假如jsontxt字段中存儲着一系列鍵值對,如果要查詢某一個鍵對應的值,那么就要使用JSON_VALUE函數  JSON_VALUE(jsontxt,'$."your key"') 。當你每一次用JSON_VALUE函數時,都會把整個jsontxt字段加載到內存中,然后再找到 your key 的值。當jsontxt數據增大后,這個查詢將會逐漸變慢。

b. 承擔表中字段的計算任務。比如:一個員工表[employees],每一個員工都有一個出生日期[birthday]字段,那么年齡字段[age]的值就可以被動態計算出來了,計算表達式:  datediff(year,birthday,getdate()) 。再例如訂單表,訂單的支付金額可以根據產品價格,產品數量,運費,優惠金額,以及 稅費 等字段計算得出。

 

你可以通過SqlServer Management Studio的UI界面操作來指定計算列,也可以通過Transact-SQL來指定計算列。

在Sql Server Management Studio中, 右鍵列 -》modify -》 新建列 -》Computed Column Specification  中來指定計算列。

 

通過Transact-SQL 來指定計算列,格式為: 列名 as 表達式 。

-- 在創建表的時候指定為計算列
create table Employees(
birthday datetime,
age as datediff(year,birthday,getdate()));


-- 在已經創建的表上添加計算列
create table Employees(birthday datetime);
alter table Employees add age as datediff(year,birthday,getdate());

 

若要指定計算列為持久化存儲(Persisted), 那么表達式中的計算結果必需是確定性的。比如上面的Age使用了getdate() 函數,這使得Age變成不確定性的,因此不能持久化Age,以及不能在Age上建立索引。

 指定計算列為持久化存儲只需要在后面加上persisted關鍵字即可,例如:

-- 在創建表的時候指定計算列
create table Products(
    id INT NOT NULL IDENTITY PRIMARY KEY,
    name nvarchar(50) not null,
    jsontxt nvarchar(4000) not null,
    [side effect] as JSON_VALUE(jsontxt,'$."side effect"') persisted
);

-- 在已經創建的表上添加計算列
create table Products(
    id INT NOT NULL IDENTITY PRIMARY KEY,
    name nvarchar(50) not null,
    jsontxt nvarchar(4000) not null

);
alter table Products add [side effect] as JSON_VALUE(jsontxt,'$."side effect"') persisted;

表Products中的jsontxt字段存儲的是JSON格式的鍵值對,是產品的詳細參數,side effect是產品中的某一個參數。為了方便管理,才將這些參數整體封裝在jsontxt字段中。

-- 插入測試數據
insert into Products(name,jsontxt) values(
'Pfizer–BioNTech COVID-19 vaccine',
'{
  "storage":"10℃",
  "type":"vaccine",
  "target":"Coronavirus",
  "side effect":"Tiredness,Headache"
 }');

計算列除了不能執行Insert, Update外,其余的和普通列一樣,直接使用計算列的列名即可:

-- 查詢數據
select [side effect] from Products where [side effect] like '%headache%';
-- output: Tiredness,Headache

-- 更新jsontxt中的值
update Products set jsontxt = JSON_MODIFY(jsontxt,'$."side effect"', 'Tiredness,Headache,Muscle pain,Chills,Fever');

-- 再次查詢數據
select [side effect] from Products where [side effect] like '%headache%';
-- output: Tiredness,Headache,Muscle pain,Chills,Fever

 

注意:

  1. 計算列不能指定INSERT, 和 UPDATE語句。
  2. persisted關鍵字不能用於含有不確定性的計算列中。
  3. 只有指定了persisted關鍵字的計算列,才會持久化存儲。如果沒指定persisted關鍵字,那么每次查詢計算列都會重新計算一遍表達式。
  4. 在創建計算列的時候,我們通常需要進行一些操作以便生成我們期望的值。這個過程中,常常需要用到SQL Server的內置函數,但並不是所有的SQL Server內置函數都是 確定性的(Deterministic),只有全是 確定性類型(Deterministic) 函數生成的動態計算列,才可以進行持久化存儲。SQL Server數據庫中所有Deterministic的內置函數列表。

參考文獻:

1. Specify Computed Columns in a Table

2. Deterministic and Nondeterministic Functions


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM