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/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 2022,我這一年|縱然來路漫漫,也有星光燦燦。
- 獲取一個字串中出現最多的字元和他的個數字串字元
- SQL 獲取SQL Server中兩個日期之間的所有日期SQLServer
- 正規表示式獲取兩個字元之間的字串資訊字元字串
- 人臉識別爭議:“錢景”燦爛,前景暗淡?
- 【資料庫】postgresql擷取最後一個字元之前的所有字元,如V1.0.0.20230731110947中取V1.0.0資料庫SQL字元
- 達摩院裡的女Leader,一面溫柔似水一面燦爛如陽
- 【SQL】SQL解惑-如何從字串中獲取IP地址SQL字串
- css 獲取從第n個開始,之後的所有元素CSS
- NSR專題 | 量子計算(特邀編輯:郭光燦、應明生)
- JavaScript獲取給定字元的unicodeJavaScript字元Unicode
- SQL 獲取SQL Server中日期最近7天之間的所有日期SQLServer
- 你說我的眼睛燦若星辰,那是因為你是星辰,而我的眼中只有你。
- 【閃閃火資料】小紅書品牌案例-雅頓橘燦精華
- EXCEL擷取某一列從第一個字元開始到特定字元結束的字串到新的一列Excel字元字串
- 利用正規表示式提取固定字元之間的字串字元字串
- SQL語法之SQL 萬用字元SQL字元
- 從外部獲取一個django專案的所有model名稱Django
- API介面的藝術:如何巧妙獲取商品資料API
- PostgreSQL 函式獲取表DDLSQL函式
- 2020年2月資料庫流行度排行:冬日雖然寒冷,春光必定燦爛資料庫
- Oracle sql 語句中帶有特殊的字元處理OracleSQL字元
- SQL server 特殊字元"u0000"處理SQLServer字元
- A站春晚備了哪些好菜?手工耿、敬漢卿、小缸和阿燦都來了
- 星光燦爛 《心跳計劃》手遊5月23日ios平臺即將上線iOS
- 《殭屍校園》演員尹燦榮確診新冠 取消《認哥》錄製等
- PostgreSQL之SQL函式介紹及實踐(一)SQL函式
- 從一個故事開始聊聊字元編碼字元
- Spring註解之@ExceptionHandler 統一異常處理和獲取方法名SpringException
- Laravel 獲取執行的sql語句LaravelSQL
- js 獲取 table 中的每一個tdJS
- java 之 給定固定長度根據字元長分割文件Java字元
- lodash原始碼分析之獲取資料型別原始碼資料型別
- bat之獲取指定幾個月前的月份資訊BAT
- 你知道怎麼從jar包裡獲取一個檔案的內容嗎JAR
- 字元流中第一個不重複的字元字元
- 寫一個獲取非行間樣式的方法
- 思否獨立開發者丨@盧燦偉:做死三個專案,累到生了一場大病,為何還要做獨立開發者