PostgreSQL 從熊燦燦一個獲取固定字元的SQL 分析巧妙之處
CASE atttypid
WHEN 21 /*int2*/ THEN 16
WHEN 23 /*int4*/ THEN 32
WHEN 20 /*int8*/ THEN 64
WHEN 1700 /*numeric*/ THEN
CASE WHEN atttypmod = -1
THEN null
ELSE ((atttypmod - 4) >> 16) & 65535
END
WHEN 700 /*float4*/ THEN 24 /*FLT_MANT_DIG*/
WHEN 701 /*float8*/ THEN 53 /*DBL_MANT_DIG*/
ELSE null
END AS numeric_precision,
CASE
WHEN atttypid IN (21, 23, 20) THEN 0
WHEN atttypid IN (1700) THEN
CASE
WHEN atttypmod = -1 THEN null
ELSE (atttypmod - 4) & 65535
END
ELSE null
END AS numeric_scale,
*
FROM
pg_attribute
where attrelid = 'xcc.xcc'::regclass and attname = 'number_b';
這個問題實際是對欄位中的一種特殊的型別numberic 進行分析,並獲取其中欄位中的兩個數字,並進行展示,聽上去很簡單。
首先我們從兩個層面去分析這個SQL
1 結構層
這個SQL 主要展示的有兩個層面 1 numeric_scale 2 numeric_scale
在基於 numeric_scale 的部分 7 個大判斷,中包含1個子判斷
numeric_scale 3個判斷,包含1個子判斷
2 判斷邏輯
首先針對 atttypid 的值進行判斷,這裡需要說明的是 atttpid 的部分的值是需要搞清楚每個值代表的意義。
我個人能想到的方法就是建立一個包含大部分欄位型別然後透過這個表來查到欄位與atttypid 之間的關係。
所以寫這個SQL 的人必然是做過這個基礎性的工作,這實際上體現了撰寫這個SQL 的人對於技術的嚴謹和認真。
判斷邏輯中首先過濾了整形的資料型別部分,int2 int4 int8 等都會被顯示,而本次提出問題的 numeric 中的欄位進行判斷在 atttypmod
這裡對於實際的計算部分進行一個解釋
numeric(5,4) => 327688 0101 0000 0000 0000 1000
第一個位元組為 numeric (n,m) 的N, 最後一個位元組為 m+4,即precision為第一個位元組,scale為最後一個位元組-4
另外為什麼atttypmod 中為什麼要減 4 ,這裡我們我們透過一個實驗可以獲得,舉例我們產生一個欄位是varchar型別 ,這裡給的值是200, 那麼我們可以看下圖atttypmod 是裡面的值是204 ,那麼從這裡就可以瞭解到為什麼上面的一個解釋中要 m+4 ,而給出的SQL 中要進行一個 atttymod -4 的工作。
最後,透過這個SQL 實際上可以看出撰寫者的對系統表的深刻理解,以及對於一些深層次系統表中 數字計算的部分,比如將 atttypmod -4 後變為16進位制後與65535 進行位與運算。
實際上這一個SQL 可以研究的地方還不少,截止目前,我也覺得並未對一些更深的問題有更深的理解。
最後這裡順道將一個大家都在用的表欄位型別表格列印的語句貼上上,PG的系統表奧妙無窮。
select
c.relname as 表名,
a.attname as 列名,
(case
when a.attnotnull = true then true
else false end) as 非空,
(case
when (
select
count(pg_constraint.*)
from
pg_constraint
inner join pg_class on
pg_constraint.conrelid = pg_class.oid
inner join pg_attribute on
pg_attribute.attrelid = pg_class.oid
and pg_attribute.attnum = any(pg_constraint.conkey)
inner join pg_type on
pg_type.oid = pg_attribute.atttypid
where
pg_class.relname = c.relname
and pg_constraint.contype = 'p'
and pg_attribute.attname = a.attname) > 0 then true
else false end) as 主鍵,
concat_ws('', t.typname) as 欄位型別,
(case
when a.attlen > 0 then a.attlen
when t.typname='bit' then a.atttypmod
else a.atttypmod - 4 end) as 長度,
col.is_identity as 自增,
col.column_default as 預設值,
(select description from pg_description where objoid = a.attrelid
and objsubid = a.attnum) as 備註
from
pg_class c,
pg_attribute a ,
pg_type t,
information_schema.columns as col
where
a.attnum>0
and a.attrelid = c.oid
and a.atttypid = t.oid
and col.table_name=c.relname and col.column_name=a.attname
order by
c.relname desc,
a.attnum asc;
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70024923/viewspace-2938837/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 獲取一個字串中出現最多的字元和他的個數字串字元
- 正規表示式獲取兩個字元之間的字串資訊字元字串
- SQL 獲取SQL Server中兩個日期之間的所有日期SQLServer
- 《卸甲筆記》-PostgreSQL和Oracle的SQL差異分析之四:特殊字元和符號筆記SQLOracle字元符號
- AWR 中 top sql 的資訊獲取 - 分析SQL
- 從mysqldump全備獲取指定庫的sqlMySql
- 【SQL】SQL解惑-如何從字串中獲取IP地址SQL字串
- css 獲取從第n個開始,之後的所有元素CSS
- 使用SQL語句從資料庫一個表中隨機獲取資料SQL資料庫隨機
- 一條很 巧妙的 SQL 語句SQL
- PostgreSQL在何處處理 sql查詢之六十六SQL
- SQL解惑-如何從字串中獲取IP地址SQL字串
- js如何查詢字元處中第一個不重複的字元JS字元
- SQL Server中獲取一個資料庫的所有表的列數SQLServer資料庫
- 巧妙設定 SQL Server獲得智慧程式碼提示SQLServer
- 利用正規表示式提取固定字元之間的字串字元字串
- 藍橋杯-從串中取三個不同字元字元
- JavaScript獲取給定字元的unicodeJavaScript字元Unicode
- SQL特殊字元處理zzSQL字元
- PostgreSQL 函式獲取表DDLSQL函式
- SQL 獲取SQL Server中日期最近7天之間的所有日期SQLServer
- 《卸甲筆記》-PostgreSQL和Oracle的SQL差異分析之五:函式的差異(一)筆記SQLOracle函式
- 巧妙使用exchange partition的一個案例
- API介面的藝術:如何巧妙獲取商品資料API
- 迴圈實現從一個陣列中按順序任意擷取幾個字元。陣列字元
- JavaScript獲取上一個元素JavaScript
- jQuery獲取上一個元素jQuery
- SQL語法之SQL 萬用字元SQL字元
- bat之獲取指定幾個月前的月份資訊BAT
- 得到固定字元位置的函式 (轉)字元函式
- 【資料庫】postgresql擷取最後一個字元之前的所有字元,如V1.0.0.20230731110947中取V1.0.0資料庫SQL字元
- 從一個故事開始聊聊字元編碼字元
- js 獲取 table 中的每一個tdJS
- jquery獲取緊鄰的上一個元素jQuery
- 解決多個路由繫結同一個元件 獲取引數只獲取一次的方法路由元件
- PostgreSQL之SQL函式介紹及實踐(一)SQL函式
- 你知道怎麼從jar包裡獲取一個檔案的內容嗎JAR
- lodash原始碼分析之獲取資料型別原始碼資料型別