# PostgreSQL ###### tags: `資料庫` `筆記` `程式` `觀念` 作為兩大主流開源數據庫,MySQL 和 Postgres ## What's postgreSQL? - 物件關聯式資料庫管理系統(ORDBMS, Object-Relational Database Management System) - 被廣泛應用於讀寫速度至關重要且資料需要驗證的大型系統中。 - 支持各種效能優化(如地理空間資料支持,不需要讀取鎖定的資料一致性支援,如 Oracle、SQL Server)。 ## 與mysql的差別 1. 開源性:PostgreSQL 是完全開源的,而 MySQL 有一部分是開源的,另一部分是商業的。 2. 許可協議:MySQL 用的是 GPL 許可協議,而 PostgreSQL 用的是 PostgreSQL 許可協議。 3. 支持的數據類型:PostgreSQL 支持更多的數據類型,包括數組、JSON 和 XML。 4. 支持的特性:PostgreSQL 支持更多的特性,包括觸發器、存儲過程、視圖、外鍵約束和規則(rule)。 5. 性能:在性能方面,MySQL 和 PostgreSQL 的表現可能有所不同,但這取決於很多因素,包括硬件、操作系統、應用程序設計和使用方式。 6. 受歡迎程度:MySQL 比 PostgreSQL 更受歡迎,因為它更流行,而且被許多大型網站和應用程序使用。 ## Pgadmin 4 - pgAdmin 是一个非常流行、功能強大並且開源的 PostgreSQL 管理與開發平台。 - pgAdmin 支持 Linux、Unix、Mac OS X 以及 Windows 操作系統,可以管理 PostgreSQL 9.2 以及更高版本。 ## 可用參數 ```htmlembedded= #進入資料庫 psql psql -h localhost -p 5432 -U [username] [DbName] #直接進入指定資料庫 # help \? # 顯示和 psql IRB 有關的指令說明 \h # 顯示和 sql 有關的指令說明 # 資料庫與資料表資訊 \du # 列出所有 roles \l # 列出所有 databases V \z or \d # 列出所有 tables \d [tablename] # 列出該資料表的所有欄位 # 連線資訊 \c [db_name] # 連線到另一個資料庫 \conninfo # 連線資訊 \password [username] # 修改某 username 的密碼 CREATE DATABASE [DbName] #創造資料庫V \c [DbName] #進入資料庫 ``` ## 基本語法 ```htmlembedded= # 建立資料表 名稱為weather和cities CREATE TABLE weather ( id BIGSERIAL NOT NULL PRIMARY KEY, city varchar(80) NOT NULL, temp_lo int, -- low temperature temp_hi int, -- high temperature prcp real, -- precipitation date date ); CREATE TABLE cities ( name varchar(80), location point ); # 刪除資料表 DROP TABLE tablename; # 新增資料 INSERT INTO weather VALUES ('San Francisco', 46, 50, 0.25, '1994-11-27'); INSERT INTO cities VALUES ('San Francisco', '(-194.0, 53.0)'); INSERT INTO weather (city, temp_lo, temp_hi, prcp, date) VALUES ('San Francisco', 43, 57, 0.0, '1994-11-29'); # 查詢資料 SELECT * FROM weather; 輸出結果: city | temp_lo | temp_hi | prcp | date ---------------+---------+---------+------+------------ San Francisco | 46 | 50 | 0.25 | 1994-11-27 San Francisco | 43 | 57 | 0 | 1994-11-29 Hayward | 37 | 54 | | 1994-11-29 (3 rows) # 限定查詢WHERE SELECT * FROM weather WHERE city = 'San Francisco' AND prcp > 0.0; # 排序 ORDER BY SELECT * FROM weather ORDER BY city; SELECT * FROM weather ORDER BY city DESC; #倒序排列 # 查詢時去除重複的列(可搭配order by) SELECT DISTINCT city FROM weather; # GROUP BY 搭配計算次數 算每個地點個出現幾次 SELECT city, COUNT(*) FROM weather GROUP BY city; # GROUP BY HAVING 印出出現超過20次的地點 SELECT city, COUNT(*) FROM weather GROUP BY city HAVING COUNT(*)>20 ORDER BY city; # 交叉查詢 SELECT * FROM weather, cities WHERE city = name; 輸出結果: city | temp_lo | temp_hi | prcp | date | name | location ---------------+---------+---------+------+------------+---------------+----------- San Francisco | 46 | 50 | 0.25 | 1994-11-27 | San Francisco | (-194,53) San Francisco | 43 | 57 | 0 | 1994-11-29 | San Francisco | (-194,53) (2 rows) # 限制條件 只出現五筆資料 SELECT * FROM cities LIMIT 5; # 限制條件 從第五筆之後開始跑5筆 SELECT * FROM cities OFFSET 5 LIMIT 5; # 重新命名 SELECT * FROM weather w, cities c WHERE w.city = c.name; SELECT cities AS weather_city From weather; # 更新資料 UPDATE SET UPDATE weather SET temp_hi = temp_hi - 2, temp_lo = temp_lo - 2 WHERE date > '1994-11-28'; # 刪除資料 DELETE DELETE FROM weather WHERE city = 'Hayward'; DELETE FROM tablename (刪除資料表內所有資料 但primary不會歸0) DELETE TABLE tablename (刪除整張表) # 查詢極值 找溫度最高的地點 SELECT city FROM weather WHERE temp_lo = (SELECT max(temp_lo) FROM weather); ``` - BIGSERIAL 自動增加的函示 - group by 和distinct的區別 - 前者通常搭配函式一起使用 - 後者也可以去除一個以上的重複資料 ![](https://i.imgur.com/XzGH01g.png) - 常用查詢函式count、sum、avg(平均值)、max、min ## 查詢語法 ```htmlembedded= # 篩選包含IN裡面的值(類似OR) SELECT * FROM cities WHERE name IN ('xxx', 'ooo') # 篩選範圍Between SELECT * FROM cities WHERE date BETWEEN DATE '2000-01-01' AND '2021-12-31'; # 模糊查詢 LIKE (包含xxx ) SELECT * FROM cities WHERE name LIKE '%xxx%' SELECT * FROM cities WHERE name NOT LIKE '%xxx%' ``` - LIKE % _ - %AB%:找包含AB - %AB : 找AB結尾 - AB%:找AB開頭 - _AB% : 找AB在第二和第三位置 - _2%3 : 找第二位置為2,並以3結束的任何值 ## 數學語法 ```htmlembedded= SELECT MAX(price) FROM car; SELECT MIN(price) FROM car; SELECT AVG(price) FROM car; SELECT ROUND(AVG(price)) FROM car; SELECT SUM(price) FROM car; #所有不同車子各自的平均(利用group by篩掉重複的項目) SELECT id, make, AVG(price) FROM car GROUP BY make; #新增一個打九折後的欄位並取道小數後第二位 SELECT make, price, ROUND(price * .90, 2) FROM car GROUP BY make; id | make | price | round(new) ------+---------------+----------+---------- 1 | GMC | 73902.36 | 66512.12 2 | Toyota | 59205.65 | 53285.09 3 | Lexus | 22672.01 | 20404.81 4 | Lexus | 30032.13 | 27028.92 5 | Mitsubishi | 14646.62 | 13181.96 ``` ## Timestamp and Date ```htmlembedded= SELECT NOW(); now ------------------------------ 2022-12-30 20:33:26.67321+08 (1 row) SELECT NOW()::DATE; // 2022-12-30 SELECT NOW()::TIME; // 20:33:59.288151 #比現在多十天 (可用來算年紀) SELECT NOW() + INTERVAL '10 DAYS'; #只取特定數字(可用YEAR or MONTH or DAY or DOW-星期) SELECT EXTRACT(YEAR FROM NOW()); ``` ## 修改表格ALTER TABLE ```htmlembedded= # 新增/刪除欄位 ALTER TABLE table_name ADD column_name datatype; ALTER TABLE table_name DROP COLUMN column_name; # 變更資料型態 ALTER TABLE table_name ALTER COLUMN column_name datatype; ``` ## Foreign Key ```htmlembedded= #資料表設定 car_id BIGINT REFERENCES car (id) #JOIN SELECT * FROM person JOIN car ON person.car_id = car.id; SELECT * FROM person LEFT JOIN car ON person.car_id = car.id; // 沒有外鍵的也會顯示 ``` ## 下載檔案 ```htmlembedded= # 將表格下載到電腦 \copy (SELECT * FROM person LEFT JOIN car ON person.car_id = car.id) TO '/Users/meme/Desktop/result.csv' DELIMITER ',' CSV HEADER; ``` ## 進階語法 ```htmlembedded= #檢視表VIEW CREATE VIEW myview AS SELECT city, temp_lo, temp_hi, prcp, date, location FROM weather, cities WHERE city = name; SELECT * FROM myview; #重複更新或新增資料 INERT INTO city (id, name) VALUE (1, 'Taipei') ON CONFLIC (id) DO NOTHING; // INSERT 0 0 ``` - 檢視表:某兩張表的內容是常用的,可以新建立檢視表,不用每次都輸入一長串的查詢語句。 其他: [Inner Join](https://pjchender.dev/database/psql-joins/) [PostgreSql](https://docs.postgresql.tw/tutorial/the-sql-language/creating-a-new-table) ## 匯入匯出檔案 ```htmlembedded= \i 檔案路徑 ex. \i /Users/meme/Downloads/person.sql ``` ## 匯入匯出資料 ```htmlembedded= COPY School(code, city, district, name) FROM '/Users/meme/Desktop/testtt.csv' DELIMITER ',' CSV HEADER; #COPY 4 回傳匯入資料數量 ```