在這主要介紹PostgreSQL IN、NOT IN的用法
IN:數值在這集合裡面。
NOT IN:數值在不再這集合裡面。
如果有一表如下:
1 | price_record |
IN:數值在這集合裡面。
1 | SELECT * FROM PRICE_RECORD PR |
結果:
1 | id | price |
NOT IN:數值在不再這集合裡面。
1 | SELECT * FROM PRICE_RECORD PR |
結果:
1 | id | price |
在這主要介紹PostgreSQL IN、NOT IN的用法
IN:數值在這集合裡面。
NOT IN:數值在不再這集合裡面。
如果有一表如下:
1 | price_record |
IN:數值在這集合裡面。
1 | SELECT * FROM PRICE_RECORD PR |
結果:
1 | id | price |
NOT IN:數值在不再這集合裡面。
1 | SELECT * FROM PRICE_RECORD PR |
結果:
1 | id | price |
最近遇到在PostgreSQL取得近幾天資料的問題,於是在思考是否有比較直覺得寫法?
後來發現用Between或>=都可以。
以下有一個table:
tb_record
1 | seq | record_date(character varying(8)) |
比如今天是,20220310則:
取得昨天到今天的資料
between寫法:
1 | SELECT |
大於等於寫法:
1 | SELECT |
結果:
1 | 5 | 20220310 |
取得近五天資料
between寫法:
1 | SELECT |
大於等於寫法:
1 | SELECT |
結果:
1 | 3 | 20220305 |
其實就是使用NOW()函數與INTERVAL條件去組日期區間去篩選(O)。
並且搭配一些內部的轉型。
以上面結果就是都轉成YYYYMMDD的字串去比較。
最近碰到一個PostgreSQL搜尋與句的問題。
就是怎樣在PostgreSQL達到類似SQL Server的Outer Apply的寫法。
因為需要在原本一對一的表,再去LEFT JOIN一個一對多資料。
並且把一對多資料取得一個結果存進一對一的表,像是Boolean、數量。
目標:
一張是訂單主表,一張是訂單明細表
想以主表為主,取得有幾張明細表數量。
Table如下:
Table ORDER
1 | SEQ |
Table ORDER_DETAIL
1 | SEQ | ORDER_SEQ | NAME |
使用 Lateral :
1 | SELECT |
結果
1 | ORDER_SEQ | ORDER_DETAIL_COUNT |
不用 Lateral:
1 | SELECT |
結果
1 | ORDER_SEQ | ORDER_DETAIL_COUNT |
用LATERAL會比較直覺,就不用最後再去GROUP BY。
如果想繼承上面LEFT JOIN表的條件,那LATERAL優勢就會出來,會顯得簡單很多。
在寫Javascript時會看到??的語法或?.的用法。
在這稍微做解釋:
?.可選鏈:
作用:可以簡化寫法,因為Javascript如果強制叫出不存在的物件會出現錯誤,所以原本寫法都要寫很長去檢查物件屬性是否存在。
1 | const user = {data:{address:"my address"}} |
可以減少巢狀物件取的屬性的程式碼。
??:
作用:左方為null或undefined則會直接回傳右方的值。
1 | const detail = {data:{address:"my address"}} |
上面因為找不到amount所以接回傳10,有的話則回傳amount
感覺未來的Javascript會充斥著 「??」、「?.」
到時候又配上Javascript函式寫法感覺閱讀性會複雜了。(雖然簡化語法,但學習門檻變高)
看自己手上的專案斟酌吧。
在這篇中介紹如何撰寫一個PostgreSQL的stored procedure。
以下是一個固定的模板,我們將以此模板來撰寫。
1 | create [or replace] procedure procedure_name(parameter_list) |
補充:
stored prodcedure沒有回傳值,所以並不會有return expression;的寫法,但你可以加return;讓程式執行到一半停止執行。
POSTGRESQL文件:
A procedure does not have a return value. A procedure can therefore end without a RETURN statement. If a RETURN statement is desired to exit the code early, then NULL must be returned. Returning any other value will result in an error
實際撰寫
目標:
撰寫一個傳送用戶ID回傳用戶資料的procedure。
users資料表:
因為PostgreSQL的stored procedure沒有回傳值,所以就要用參考的方式去拿值。
以下用INOUT refcursor refcursor去當作參考。
IN user_id integer則是要取得資料的使用者id。
1 | CREATE OR REPLACE PROCEDURE get_user_data |
建好後可在左方PGADMIN看到
之後可以用call來執行。
建立一個區域,宣告一個RECORD物件用來印資料、一個refcursor物件用來參考
接著跑loop迴圈,將每個out_ref放進rcd,再用raise notice印出。
如果沒資料則用IF判斷式離開。
1 | DO $$ |
結果:
PostgreSQL的prodcedure並不好寫,因為他沒辦法直接有返回值。要用參考的方式。他不像SQL Server一樣簡單,能直接Select完畢,因為並不具備回傳值。要回傳值就得寫他的function,就不是prodcedure了。
然後,如果想參考SQL Server的prodcedure我之前也有寫一篇:SQL-Server-Stored-Procedure實作範例可以參考。
最近剛好有要在SQL Server中Left Join N筆結果排序後只取得第一筆的需求。
發現Left Join資料結果會有問題,所以發現了Outer Apply作法能夠達到,因此筆記一下。
需求:
撈出每位使用者還沒完成的最早一筆任務。
並以Priority做排序,如果遇到相同層級則以最早新建的資料為主。
Todos資料表:
Users資料表:
sql:
1 | SELECT |
執行結果:
SQL Server有些特殊語法,有時真的得在實作時才會真的碰到。(坑)
因為最近有碰PostgreSQL的需要,因此來整理儲存型別。
此外,發現PostgreSQL的欄位型態具有Alias別名,所以有些型別找不到就要參考文件的Alias。
在以下只列常見的型別,更多請自己參閱參考資料。
名稱 | 描述 | 備註 |
character varying(n), varchar(n) | 可變長度,但有限制 | 其中 n 是正整數。可以長度最多為 n 個字元(不是位元組)的字串。 |
character(n), char(n) | 固定長度,空白填充 | 其中 n 是正整數。可以長度最多為 n 個字元(不是位元組)的字串。 |
text | 可變且無限長度 |
名稱 | 描述 | 備註 |
smallint | 2 bytes ,-32768 to +32767 | |
integer | 4 bytes,-2147483648 to +2147483647 | |
bigint | 8 bytes,-9223372036854775808 to +9223372036854775807 | |
numeric | up to 131072 digits before the decimal point; up to 16383 digits after the decimal point。可調式精確度數值型別 | Alias decimal |
real | 4Bytes,6 decimal digits precision 非精度浮點數型別 | |
double precision | 8Bytes,15 decimal digits precision 非精度浮點數型別 |
名稱 | 描述 | 備註 |
boolean | 1Bytes |
名稱 | 描述 | 備註 |
timestamp [ (p) ] [ without time zone ] | 8 bytes, both date and time (no time zone), 4713 BC ~ 294276 AD | |
timestamp [ (p) ] with time zone | 8 bytes, both date and time, with time zone, 4713 BC ~ 294276 AD |
在這篇中以一個熟悉SQL Server的角度,列出了平常可能會見到的PostgreSQL資料型態。
因為後者的資料型別彈性高(能夠自己建立物件存進、支援儲存JSON等等),所以等後面實際碰到再額外補充。
而完整的型別請自行參考網址的參考資料吧!
可能會有人有疑問怎沒SQL Server的NVARCHAR?
Generally you just use a UTF-8 encoded DB, and everything works with no hassle.
在開資料時在存字串常會有選擇上的問題,到底該存哪種型別?
而在此就稍微介紹NVARCHAR、VARCHAR的差異。
以SQL Server 2019資料庫為準。
n表示可變大小字串資料。 n 會定義字串大小 (單位為位元組配對),且可以是 1 到 4,000 之間的值。max 表示儲存大小上限是 2^30-1 個字元 (2 GB)。
使用 n 以位元組為單位來定義字串大小,該值可以介於 1 到 8,000,或使用 max 來表示資料行大小限制最多為 2^31-1 個位元組 (2 GB) 的儲存體。
NVARCHAR | VARCHAR | |
Unicode支援 | 有 | 無 |
每個字元儲存容量 | 英文字元2 Byte;非英文字元2 Byte | 英文字元1 Byte;非英文字元2 Byte |
儲存長度 | 不定長,依照資料內容 | 不定長,依照資料內容 |
n的長度限制 | 1~4000(表示可以用寫4000個中、英文字元) | 1~8000(表示可以用寫8000個英文字元) |
max | 2GB | 2GB |
結論 | 要儲存英文以外的用NVARCHAR,可以避免亂碼問題,但儲存空間相較VARCHAR會多一些。 | 只存英文VARCHAR沒問題,存其他可能會有亂碼問題。 |
使用NVARCHAR來儲存字串會比較好,因為可避免字串因為中英混雜亂碼。
https://docs.microsoft.com/zh-tw/sql/t-sql/data-types/char-and-varchar-transact-sql?view=sql-server-ver15
https://docs.microsoft.com/zh-tw/sql/t-sql/data-types/nchar-and-nvarchar-transact-sql?view=sql-server-ver15
https://ithelp.ithome.com.tw/articles/10213922
在這篇文章中介紹如何用C#產生PDF檔案。
使用套件為IText7。
IText7:https://itextpdf.com/en/products/itext-7/itext-7-core
程式碼範例:https://github.com/yuhsiang237/csharp-notes/tree/master/IText7Sample
先用Nuget安裝:
1 | Install-Package itext7 |
如下,以下為產生一個PDF檔案,並加入標題。
其中標題為中英文混雜。
Program.cs
1 | using iText.Kernel.Font; |
可以使用此套件來快速產生PDF,如果有中文需求可以像我上面那樣自己去補中文字型即可。