文章目錄
- Postgre/Gauss
- 字符串拼接:
- 數據類型轉換:
- 當數字類型小於1時轉換爲字符類型後小數點前面的0不顯示:
- coalesce函數:
- 隨機數random()函數:
- 日期字段截取:
- 將字符串類型的數據“20200308191233”轉換成時間格式並精確到秒:
- 將字符串類型的數據“20200308191233”轉換成時間戳格式:
- 字符串截取函數:
- 分割函數:
- replace函數:
- 四捨五入、向上取整、向下取整:
- 取整取餘:
- 前10行:
- 實現分頁功能:
- not exists用法:
- like用法:
- 正則表達式:
- 轉義字符:
- 日期加減:
- bbyf字段格式爲“2019-11-01 00:00:00”,csrq(出生日期)字段格式也一樣,計算年齡:
- 查詢某個日期之前的數據(包括這個日期):
- 使用case when查如果兩列不一致則賦個值的需求:
- 把a表的數據插入到b表時id是以在b表最大id的基礎上實現自增:
- 把查詢的結果插入另一張表的兩張方式:
- update和select結合使用:
- 用戶解鎖:
- 刪除用戶:
- 創建用戶並賦予密碼:
- 創建數據庫並使某用戶擁有:
- 修改用戶密碼:
- 賦予用戶所有權限:
- 查詢都有什麼用戶:
- 查詢都有什麼數據庫、庫下有什麼模式、模式下有什麼表、表裏什麼字段:
- 創建schema:
- 判斷某個schema是否存在:
- 創建主鍵並設置自動遞增的三種方法:
- 創建臨時表:
- 查詢臨時表屬性:
- 查詢庫下的所有外表:
- 查看錶大小:
- 查看指定庫大小:
- 查看所有數據庫大小:
- 查看待刪除涉及query_id、pid:
- 給列添加備註:
- 給表增加列:
- 索引:
- 查看索引有沒有生效:
- 表空間:
- \set用法:
Postgre/Gauss
字符串拼接:
函數:concat('201911','01')
結果:2011101
數據類型轉換:
函數:cast(month_id as timestamp)
注意:當month_id值爲2011101時纔可以轉換爲timestamp成功,即轉換後值爲2019-11-01 00:00:00,如果month_id值爲20111時則轉換失敗
錯誤代碼:[0][SQLErrorCode : 3295]ERROR: date/time field value out of range: "201911"
Hint: Perhaps you need a different "datestyle" setting.
當數字類型小於1時轉換爲字符類型後小數點前面的0不顯示:
目前我也沒有找到什麼好的方法,只能用case when判斷然後再進行拼接了
case
when left(cast(cast(q.jdyysr as numeric(14,4)) as text),1)='.' then concat('0',cast(cast(q.jdyysr as numeric(14,4)) as text))
else cast(cast(q.jdyysr as numeric(14,4)) as text)
end jdyysr
coalesce函數:
select coalesce(success_cnt, 1) from tableA;
解釋:當success_cnt 爲null值的時候,將返回1,否則將返回success_cnt的真實值。
備註:nvl和ifnull函數也有這個效果,但是經我測試只有coalesce函數在Postgre、SQLserver、mysql中都適用,nvl只在Postgre中可以使用,而ifnull只可以在mysql中使用
隨機數random()函數:
--隨機字母
select chr(int4(random()*26)+65);
--隨機4位字母
select repeat(chr(int4(random()*26)+65),4);
--隨機數字 十位不超過6的兩位數
select (random()*(6^2))::integer;
--三位數
select (random()*(10^3))::integer;
日期字段截取:
to_char(jsrq,'yyyy')='2019'要比left(jsrq,4)='2019'速度快將近一倍
select count(1) from tpcds.gr_yljf_yzh where left(jsrq,4)='2019'; 用時1 mins, 41 sec
select count(1) from tpcds.gr_yljf_yzh where to_char(jsrq,'yyyy')='2019'; 用時50 sec
注:表中有107675358條數據,jsrq(結算日期)字段數據格式爲“2019-11-01 00:00:00”
將字符串類型的數據“20200308191233”轉換成時間格式並精確到秒:
select to_date('20200308191233');
結果:2020-03-08 19:12:33
注意:當有想把某一個字符類型字段轉換成時間格式時發現該字段有爲null的數據該如何辦呢,直接轉的話會報錯the format is not correct!
解決:
select
case
when "合同結束日期" is null then to_date('')
else to_date(concat("合同結束日期",'000000'))
end htjsrq
from
tpcds.hehe;
將字符串類型的數據“20200308191233”轉換成時間戳格式:
SELECT cast(EXTRACT(EPOCH FROM TIMESTAMP WITH TIME ZONE '2016-05-25 14:30:50.352')*1000 as character varying(14));
運行結果:1464157850352
SELECT cast(EXTRACT(EPOCH FROM TIMESTAMP WITH TIME ZONE '2016-05-25 14:30:50')*1000 as character varying(14));
運行結果(該結果和用java轉換的結果一致):1464157850000
SELECT cast(EXTRACT(EPOCH FROM TIMESTAMP WITHOUT TIME ZONE '2016-05-25 14:30:50.352')*1000 as character varying(14));
運行結果:1464186650352
可以在該頁面校驗一下:https://tool.lu/timestamp/
業務語句:select cast(EXTRACT(epoch from cast(to_date(sqsj) as TIMESTAMP WITH TIME ZONE))*1000 as character varying(14)) from hehe.shbxhj_jcsj;
備註:sqsj字段的值格式爲“20200309105222”
字符串截取函數:
select substr('2019-11-02',6,2);
select substring('2019-11-02',6,2);
備註:運行結果都爲11,其中substr函數在gauss中可用,SQLserver中不可用
分割函數:
select split_part('8a59-e88177-ad5e70' ,'-', 3);
如果分割符數量不一樣怎麼辦,這裏就要計算分割符的數量了:
select split_part('8a59-e88177-ad5e70' ,'-', length(replace('8a59-e88177-ad5e70','-','--')) - length('8a59-e88177-ad5e70') + 1);
運行結果:ad5e70
replace函數:
問題:select '1294.00'/1000;
報錯:ERROR: invalid input syntax for integer: "1294.00"
解決:select REPLACE('1294.00','.00','')/1000;
四捨五入、向上取整、向下取整:
round() 函數是四捨五入用,第一個參數是我們要被操作的數據,第二個參數是設置我們四捨五入之後小數點後顯示幾位。
如:round(12.555,2) 結果:12.56
向上取整:select ceiling(45.88); 結果:46
向下取整:select floor(45.99); 結果:45
取整取餘:
取整:trunc(176/12)
結果:14
取餘:mod(176,12)
結果:8
前10行:
SELECT * FROM shbxhjzt.shbxhj_jcsj order by dwdm limit 10;
或者:
SELECT * FROM shbxhjzt.shbxhj_jcsj order by dwdm fetch first 10 rows only;
備註:在SQLserver中只能用top,上面兩種都不支持,同樣gauss也不支持top用法
select top 10 * from [lf_jybtjcpg].[dbo].[code_hangyexingzhi];
注意:最好加上order by,要不每次結果不一樣
補充:
1、SQL server的語法:
SELECT TOP number|percent column_name(s) FROM table_name;
例子:從表persons中選取前2行的數據;
SELECT TOP 2 * FROM persons;
從表persons中去前50%的 數據:
SELECT TOP 50 percent * from persons;
2、MySQL的語法:
SELECT column(s) FROM table_name LIMIT number;
例子:查看前5行數據:
SELECT * FROM persons LIMIT 5;
3、Oracle的語法:
SELECT * FROM table_name where ROWNUM<=number;
例子:查看前5行的數據:
SELECT * FROM persons where ROWNUM <=5;
實現分頁功能:
select
*
from
(
select
row_number() over(order by ID asc) as rownumber,*
from
shbxhjzt_tmp.shbxhj_sqhjdwxx
where
sqsj>='2020-03-01' and sqsj<='2020-03-31'
) temp_row
where
rownumber>(4-1)*9 fetch first 9 rows only;
備註:修改where後面的值即可達到分頁的功能,如第一頁展現9條數據爲rownumber>(1-1)*9,第二頁爲rownumber>(2-1)*9
not exists用法:
select
distinct dwdm
from
shbxhjzt.shbxhj_jcsj a
where
not exists (select 1 from shbxhjzt_tmp.shbxhj_jcsj_eight b where a.dwdm = b.dwdm)
and not exists (select 1 from shbxhjzt_tmp.shbxhj_jcsj_eighteen b where a.dwdm = b.dwdm);
select grid from tpcds.gr_xx_201912 a where exists (select sfzhm from mdl_ddpt_tmp.t_ryhx_zrrpj b where a.bzhm=b.sfzhm)
like用法:
select * from lsxgwbtzt.lsxgwbt_hmcryxx where sfzhm like '%X';
select * from lsxgwbtzt.lsxgwbt_hmcryxx where sfzhm not like '%X';
正則表達式:
說明:在postgresql中使用正則表達式時需要使用關鍵字“~
”,以表示該關鍵字之前的內容需匹配之後的正則表達式,若匹配規則不需要區分大小寫,可以使用組合關鍵字“~*
”;
相反,若需要查詢不匹配這則表達式的記錄,只需在該關鍵字前加否定關鍵字“!
”即可。若正則表達式包含轉義字符,則需在表達式前加關鍵字“E
”。
匹配email地址以A-H開頭的記錄:
select * from user where email ~ '^[A-H]';
過濾sfzhm字段不是身份證格式的數據:
select * from lsxgwbtzt.lsxgwbt_hmcryxx where sfzhm !~ '^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$';
轉義字符:
在PostgreSQL 9之前的版本中,可以直接使用反斜槓\
進行轉義;比如:\b
表示退格, \n
表示換行, \t
表示水平製表符,\r
標示回車,\f
表示換頁。除此之外還支持\digits
和\xhexdigits
,分別表示轉義八進制和十六進制數據。
但是在PostgreSQL 9之後的版本,反斜槓已經變成了普通字符;如果想要使用反斜槓來轉義字符,就必須在需要轉義的字符串前面加上E
(E就是Escape),如下:select E'張\t小明';
對單引號的兩種轉義方式:
在SQL標準中字符串是用單引號括起來的,而在PostgreSQL中遵守了該標準,雙引號則是用來表示變量的,如果在字符串中需要使用到單引號,就需要對其進行轉義。
方式一:使用E和反斜槓進行轉義select E'\'233';
方式二:直接用一個單引號來轉義單引號select '''233'
;
這兩種方式都能得到'233
的結果而不會報錯,第二種方式比較簡單,也可以通過修改standard_conforming_strings參數的值來讓反斜槓從普通字符變回轉義字符:
show standard_conforming_strings;
SET standard_conforming_strings = on;
SET standard_conforming_strings = off;
當該參數的值爲off時就可以直接使用反斜槓作爲轉義字符裏,如下:select '\'233';
將會得到'233
的結果而不會報錯。
來自:https://www.cnblogs.com/yulinlewis/p/9471721.html
注意:在實踐中遇到這麼個神奇的問題,在gsql裏執行這兩條語句都沒問題,但是在datastudio或者代碼中運行則會一條失敗一條成功。
失敗:
insert into tpcds.hehe(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19,t20,t21,t22,t23,t24,t25,t26,t27,t28,t29,t30,t31) VALUES
('123456','123456','123456','null','123456','123456','1','123456','01','40','1','123456','9','null','0','null','null','null','null','1','小城村\','123456','123456','null','0','null','13521390418','null','null','1','20');
成功:
insert into tpcds.hehe(t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19,t20,t21,t22,t23,t24,t25,t26,t27,t28,t29,t30) VALUES
('123456','123456','null','123456','123456','1','123456','01','40','1','123456','9','null','0','null','null','null','null','1','小城村\','123456','123456','null','0','null','13521390418','null','null','1');
失敗:
insert into tpcds.hehe(t21,t22,t23,t24,t25,t26,t27,t28,t29,t30,t31) VALUES
(E'小城村\','123456','123456','null','0','null','13521390418','null','null','1','20');
整了半天咋也不知道啥原因,後來改變了思路,可以成功了,就是把反斜槓替換成反斜槓的Unicode碼插入則不會報錯了。即
insert into tpcds.hehe(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19,t20,t21,t22,t23,t24,t25,t26,t27,t28,t29,t30,t31) VALUES
('123456','123456','123456','null','123456','123456','1','123456','01','40','1','123456','9','null','0','null','null','null','null','1',E'小城村\u005c','123456','123456','null','0','null','13521390418','null','null','1','20');
提供兩個轉碼工具的連接:http://www.bejson.com/ 和 https://www.sojson.com/ascii.html(讓這個網站搞蒙了,在裏面輸入“\”,然後點擊字符轉換ASCII會生成結果“\u005c”,但前一個網站輸入“\u005c”再點擊“unicode轉中文”生成結果爲“\”,那麼\u005c到底是Unicode碼還是ASCII碼呢?有知道的網友可以留下言)
注意:轉換成Unicode碼插的時候目前測出有兩個是無法插入的,一個是\ufeff
,另一個是\u0000
,但是\u0001
就可以。
日期加減:
postgres=# select sysdate;
sysdate
---------------------
2020-02-12 14:03:25
(1 row)
相加:
postgres=# select sysdate + '2 month';
?column?
---------------------
2020-04-12 14:03:44
(1 row)
相減:
postgres=# select concat(to_char(sysdate + '-2 month','yyyymm'),'01');
concat
----------
20191201
(1 row)
bbyf字段格式爲“2019-11-01 00:00:00”,csrq(出生日期)字段格式也一樣,計算年齡:
cast((date_part('year',age(sysdate,csrq))*12+date_part('month',age(sysdate,csrq)))/12 as int) nlid
查詢某個日期之前的數據(包括這個日期):
select grid,csrq from sdp_jcsj.t_gaj_jc_hujirenkouxinxi_tmp where age(csrq,'1981-02-03')<=0;
使用case when查如果兩列不一致則賦個值的需求:
select case when sbkh=jydjh then '12472904100S' else '112' end hehe from sdp_jsc.t_ywdt_sbkjsjk;
而不能寫成(報錯,語法不對):select case sbkh when sbkh=jydjh then '12472904100S' else '112' end hehe from sdp_jsc.t_ywdt_sbkjsjk;
對的語法:select case sbkh when '12472904100S' then '12472904100S' else '112' end hehe from sdp_jsc.t_ywdt_sbkjsjk;
把a表的數據插入到b表時id是以在b表最大id的基礎上實現自增:
INSERT INTO gc_shiyefeirenyuan
(id
,tjrq
,dwid
,sbqncszrs
,btje
,sqxzqhdm
,rdqylx)
SELECT row_number() over(order by bbny) + t2.sk_max,bbny
,dwid
,sbqncszrs
,btje
,sqxzqhdm
,rdqylx
FROM y_shiyebaoxianfeiyongkuanjihua
cross join (select coalesce(max(gc_shiyefeirenyuan.id),0) sk_max from gc_shiyefeirenyuan) t2
where bbny='201906' and if(btje is null,0,btje)>0;
把查詢的結果插入另一張表的兩張方式:
(1)select * into hehe from haha;
(2)create table hehe as select * from haha;
update和select結合使用:
UPDATE table1 t1
SET column1 = t2.columnname1,
column2 = t2.columnname2
FROM (select columnname1,columnname2 from table2) t2
WHERE t1.column3 = t2.column3
AND t1.column = '111';
用戶解鎖:
ALTER USER jack ACCOUNT UNLOCK;
刪除用戶:
DROP USER jack CASCADE;
注:如果用該用戶執行了插入數據等則上述命令將不能執行成功,即不能刪除有數據的用戶(我當時是用Jack用戶執行了GaussDBTest.jar創建customer_t1並插入了數據,將這個表刪除之後就可以將該用戶刪除了)
postgres=# drop user jack;
ERROR: role "jack" cannot be dropped because some objects depend on it
DETAIL: 1 object in database hwbase
創建用戶並賦予密碼:
CREATE USER hui PASSWORD 'hehe';
創建數據庫並使某用戶擁有:
create database hui owner hui;或者CREATE DATABASE hui WITH OWNER=hui;
GRANT CONNECT ON DATABASE hui TO hui;
修改用戶密碼:
alter user jack identified by "heheda";
注:密碼不能複用
賦予用戶所有權限:
GRANT ALL PRIVILEGES TO hui;
查詢都有什麼用戶:
SELECT * FROM PG_TOTAL_USER_RESOURCE_INFO;
查詢都有什麼數據庫、庫下有什麼模式、模式下有什麼表、表裏什麼字段:
查詢都有什麼庫(相當與mysql的show databases):select datname from pg_database;
查詢庫下有什麼模式:SELECT table_catalog,table_schema FROM information_schema.columns where table_catalog='db_perfect' group by table_catalog,table_schema;
查詢模式下有什麼表(相當於mysql的show tables):SELECT table_name FROM information_schema.tables WHERE table_schema = 'public';
或者select tablename from pg_tables where schemaname='public';
查詢表裏有什麼字段(相當與mysql的describe table_name):SELECT column_name FROM information_schema.columns WHERE table_name ='code_jntspxgz' and table_catalog='db_perfect' and table_schema='sdp_jcsj';
創建schema:
CREATE SCHEMA wuxian_shiye;
判斷某個schema是否存在:
SELECT EXISTS(SELECT 1 FROM information_schema.schemata WHERE schema_name = 'sjhj');
SELECT EXISTS(SELECT 1 FROM pg_namespace WHERE nspname = 'sjhj');
兩種方式都可以,第二個更有效率一些。
創建主鍵並設置自動遞增的三種方法:
來自:http://francs3.blog.163.com/blog/static/40576727201111715035318/
方法一:
create table test_a
(
id serial,
name character varying(128),
constraint pk_test_a_id primary key( id)
);
方法二:
create table test_b
(
id serial PRIMARY KEY,
name character varying(128)
);
方法三:
create table test_c
(
id integer PRIMARY KEY,
name character varying(128)
);
CREATE SEQUENCE test_c_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
alter table test_c alter column id set default nextval('test_c_id_seq');
很明顯從上面可以看出,方法一和方法二隻是寫法不同,實質上主鍵都通過使用 serial 類型來實現的,使用serial類型,PG會自動創建一個序列給主鍵用,當插入表數據時如果不指定ID,則ID會默認使用序列的NEXT值。
方法三是先創建一張表,再創建一個序列,然後將表主鍵ID的默認值設置成這個序列的NEXT值。這種寫法似乎更符合人們的思維習慣,也便於管理,如果系統遇到sequence 性能問題時,便於調整 sequence 屬性;
三個表表結構一模一樣, 三種方法如果要尋找差別,可能僅有以下一點,當 drop 表時,方法一和方法二會自動地將序列也 drop 掉, 而方法三不會。
創建臨時表:
create TEMPORARY table temp1 as select * from tpcds.事_單位信息;
查詢臨時表屬性:
select * from pg_catalog."pg_class" where relname = 'temp1';
查詢庫下的所有外表:
select oid,* from pg_class where oid in (select ftrelid from pg_foreign_table);
查看錶大小:
select pg_size_pretty(pg_table_size('tpcds."事_單位信息"'));
查看指定庫大小:
select pg_size_pretty(pg_database_size('postgres'));
查看所有數據庫大小:
select pg_database.datname, pg_size_pretty(pg_database_size(pg_database.datname)) AS size from pg_database;
查詢結果:
template1 88 MB
hwbase 621 GB
wuxian 95 GB
template0 88 MB
postgres 102 MB
查看待刪除涉及query_id、pid:
Select query,query_id,pid from pg_stat_activity where query like '%faren_jichushuju_20191115_ext%';
select pg_cancel_backend(140585035888384); --殺死進程
給列添加備註:
comment on column sdp_jsc_test.cbfbqk.rq is '創建日期';
給表增加列:
alter table tmp1 add xzqmc varchar(50);
索引:
--查詢索引
select * from pg_indexes where tablename='t_source_dwxx';
--創建索引
create index t_source_dwxx_index on ycxjycyfwbt.t_source_dwxx(dwid);
--刪除索引
drop index ycxjycyfwbt.t_source_dwxx_index;
查看索引有沒有生效:
explain analyze select * from heheda.haha where sfzhm='110';
或者
explain performance select * from heheda.haha where sfzhm='110';
注:
EXPLAIN PERFORMANCE statement:生成執行計劃,進行執行,並顯示執行期間的全部信息。
EXPLAIN ANALYZE statement:生成執行計劃,進行執行,並顯示執行的概要信息。顯示中加入了實際的運行時間統計,包括在每個規劃節點內部花掉的總時間(以毫秒計)和它實際返回的行數。
注意:執行這個命令可能出不來index,得先執行該命令set enable_fast_query_shipping=off;
每加該條命令之前執行explain analyze命令:
之後:
表空間:
--創建表空間
CREATE TABLESPACE huihui1 RELATIVE LOCATION 'tablespace1/huihui1';
--查詢都有什麼表空間
SELECT * FROM pg_tablespace;
--刪除表空間
DROP TABLESPACE huihui1;
\set用法:
postgres=# \set monthid1 20191001
或者:
postgres=# \set monthid1 '20191001'
postgres=# select :'monthid1';
?column?
----------
20191001
(1 row)
postgres=# select :monthid1;
?column?
----------
20191001
(1 row)
postgres=# \set monthid1 'select 20191001'
或者:
postgres=# \set monthid1 'select '20191001''
postgres=# :monthid1;
?column?
----------
20191001
(1 row)
postgres=# (:monthid1);
?column?
----------
20191001
(1 row)
postgres=# create TEMPORARY table month_table as select concat(to_char(sysdate + '-2 month','yyyymm'),'01') rq;
NOTICE: The 'DISTRIBUTE BY' clause is not specified. Using 'rq' as the distribution column by default.
HINT: Please use 'DISTRIBUTE BY' clause to specify suitable data distribution column.
INSERT 0 1
postgres=# \set monthid1 'select rq from month_table'
postgres=# select rq from month_table where rq=(:monthid1);
rq
----------
20191201
(1 row)