基于PostgreSQL和mysql数据类型对比兼容

1、数值类型

整数:

mysql中的整数类型和pg相比,两者有以下区别:

mysql:mysql中支持int 1,2,3,4,8 字节,同时支持有符号,无符号。并且mysql中支持在数值列中指定zerofill,用来将存储的数值通过填充0的方式达到指定数据类型的长度(mysql8开始不建议使用ZEROFILL属性,并且在将来的MySQL版本中将不再支持该属性)。

pg:pg支持 int 2,4,8 字节,且数值都是有符号的。

mysql整数类型:

pg整数类型:

那么对于mysql中的1,3字节整型,或者无符号整型以及zerofill特性,在pg中该如何实现呢?

在pg中我们可以使用domain来实现mysql中的1,3字节整数以及无符号整型。

创建uint8,8字节无符号整型

bill=# create domain uint8 as numeric(20,0) check (value <= ((2^64::numeric)::numeric(20,0)-1) and value>=0::numeric(20,0));
CREATE DOMAIN

使用domain,插入整型数据,且大于等于0,小于2^64

bill=# create table t5(c1 uint8);
CREATE TABLE
bill=# insert into t5 values (-1);
ERROR: value for domain uint8 violates check constraint "uint8_check"
bill=# insert into t5 values (0);
INSERT 0 1
bill=# insert into t5 values (18446744073709551615);
INSERT 0 1
bill=# insert into t5 values (18446744073709551616);
ERROR: value for domain uint8 violates check constraint "uint8_check"
bill=# select * from t5;
  c1
----------------------
   0
 18446744073709551615
(2 rows)

同样我们也可以来创建domain实现1,3字节有无符号整型,2,4,8字节无符号等等:

create domain int1 as int2 CHECK (VALUE <= 127 AND VALUE >= (-128));
create domain uint1 as int2 CHECK (VALUE <= 255 AND VALUE >= 0);
create domain uint2 as int4 CHECK (VALUE <= 65535 AND VALUE >= 0);
create domain int3 as int4 CHECK (VALUE <= 8388607 AND VALUE >= (-8388608));
create domain uint3 as int4 CHECK (VALUE <= 16777215 AND VALUE >= 0);
create domain uint4 as int8 CHECK (VALUE <= 4294967295 AND VALUE >= 0);
create domain uint8 as numeric(20,0) check (value <= ((2^64::numeric)::numeric(20,0)-1) and value>=0::numeric(20,0));

而对于mysql中的zerofill,我们可以使用lpad函数来实现,并且这也是mysql官方文档中推荐的一种方式。

mysql中zerofill使用方式:

mysql> create table t1(id int1 zerofill);
Query OK, 0 rows affected (0.00 sec)

mysql> insert into t1 values(4);
Query OK, 1 row affected (0.00 sec)

mysql> select * from t1;
+------+
| id |
+------+
| 004 |
+------+
1 row in set (0.00 sec)

pg中使用lpad函数替代:

bill=# create table t1(id int);
CREATE TABLE
bill=# insert into t1 values (123),(123456);
INSERT 0 2
bill=# select lpad(id::text, greatest(4, length(id::text)), '0'), id from t1;
 lpad | id
--------+--------
 0123 | 123
 123456 | 123456
(2 rows)

numeric类型:

pg和mysql一样都支持decimal,numeric类型来表示浮点数。两者的区别在于:mysql中的numeric类型整数和小数部分均最大支持65digits。

而pg中numeric类型支持的最大范围是:

[左131072,右16383]digits。

例如:

–mysql中

mysql> create table t1(id numeric(66,1));
ERROR 1426 (42000): Too-big precision 66 specified for 'id'. Maximum is 65.
mysql> create table t1(id numeric(65,1));
Query OK, 0 rows affected (0.01 sec)

–pg中

bill=# create table t4(id numeric(66,1));
CREATE TABLE

浮点类型:

mysql和pg中的浮点数类型基本一致。mysql中4 bytes的浮点数类型有real,float4,4 bytes的浮点数类型double。pg中对应的也有real,float,float4,float8以及double precision,两者基本兼容。

bit类型:

mysql中bit类型一般都是使用整数类型表示,所以支持的bit位数最大只能是64位。而在pg中有专门的bit类型bit(范围1~83886080),以及可变长度的bit类型varbit。

序列:

mysql中创建表时可以使用auto_increment来创建自增列,从而生成一个和该列相关的序列,这个和pg中创建serial类型的列类似,但是两者仍然有明显区别:

mysql:使用auto_increment的自增列必须要建索引,不然会报错。序列的默认初始值是1,步长为1.可以通过修改auto_increment_increment和auto_increment_offset来修改初始值和步长。

pg:pg中创建serial类型的列时会创建相应的序列,支持的数据类型有serial2,serial4,serial8。同时pg创建序列时可以直接指定初始值,步长,maxvalue,cache,circle等参数。其中序列cache预取多个值,可以保证没有性能问题。circle可以指定序列达到最大值后从初始值开始重新计数。

–mysql

mysql> create table t4 (id int auto_increment primary key);
Query OK, 0 rows affected (0.06 sec)
–PostgreSQL

bill=# create table t4(id serial);
CREATE TABLE

2、时间类型

mysql:mysql中时间相关的类型有日期date、时间time以及datetime、timestamp和year类型。

pg:pg中的时间数据类型基本和mysql一致。区别在于pg中支持timez类型,即带时区的时间类型,这个mysql中不支持,但是pg中不支持mysql中的year类型,不过我们仍然可以通过创建domain的方式来在pg中实现year类型。

mysql中的year类型表示年份从 1901年到2155。

pg中实现mysql中year类型的方式:

bill=# create domain year as int2 check(value >=1901 and value <=2155);
CREATE DOMAIN
bill=# create table ts4(c1 year);
CREATE TABLE
bill=# insert into ts4 values (1000);
ERROR: value for domain year violates check constraint "year_check"
bill=# insert into ts4 values (2019);
INSERT 0 1
bill=# insert into ts4 values (2156);
ERROR: value for domain year violates check constraint "year_check"

3、字符串类型

char/varchar类型:

mysql和pg中都支持char类型来表示固定长度的字符串,varchar类型表示可变长度的字符串类型,两者的区别在于:

mysql:char类型最大255字符,varchar类型最大不超过64字节。

pg:char类型最大10485760字符,varchar类型最大1G字节。同时pg中还支持两种特殊的字符串类型:name类型,固定64字节长度,char类型(即不指定长度),固定1字节长度。

binary/varbinary类型:

mysql中binary(n)最大255个字符,varbinary(n)最大不超过64k字节。使用字节流来存储字符串。而pg中使用bytea类型来表示二进制类型,最大不超过1G字节。

blob/text类型:

mysql中的blob/text类型分别有以下几种:

tinyblob、tinytext < 2^8字节

blob、text < 2^16字节

mediumblob、mediumtext < 2^24字节

longblob、longtext < 2^32字节

pg中对应的使用bytea类型和text类型,两者最大长度均为1G字节。

enum类型:

mysql中的枚举类型最大不超过64K个值,而pg中最大为1GB

set类型:

mysql中的集合set类型表示没有重复值的集合,最大64个值,在pg中虽然没有set类型,但是可以通过数组类型去代替,最大支持1GB大小。

4、其它类型

json类型:

mysql和pg中的json类型基本一致,区别在于默写json函数可能稍有区别。不过pg中json类型有2种json和jsonb,不过一般都使用jsonb类型。

除了上面列举的这些类型之外,pg中还支持很多mysql中不支持的数据类型。例如:pg中支持IP地址类型,这个在mysql中常常都是使用int或者varchar之类的数据类型代替。

除此之外还有很多pg内置的数据类型在mysql中是不支持的:货币、interval、平面几何、全文检索、uuid、xml、数组、复合类型、范围类型、域类型等等。

同时pg还有很多外置的数据类型:树类型、多维类型、化学分子、DNA、postgis等等类型。

补充:Oracle与PostgreSQL使用差异对比与总结

JDBC连接:

Oracle的jdbc连接字符串:db.url=jdbc:oracle:thin:@192.168.1.1:1521:ORCL

Postgresql的连接字符串:db.url=jdbc:postgresql:@192.168.1.1:5432/database

1、基本数据类型差异

Oracle PostgreSQL
Varchar2 varchar
number numeric
date timestamp/date/time
不支持boolean,可通过0/1代替 支持boolean
null null

2、基本函数差异

item Oracle PostgreSQL
系统当前时间 SYSDATE
now()/CURRENT_TIMESTAMP/CURRENT_DATE/CURRENT_TIME

对时间或数字截取 trunc() date_trunc()
to_char,to_number, to_date 自动格式转换
需指定日期格式

eg:to_date(timejoin,'yyyy-MM-dd')

判空操作 nvl() coalesce()
条件判断 decode() case...when...then
dual伪表 支持 不支持(查询常量不需要加from)

其他用法一致的常用函数:

mod(n2,n1) -- n2除n1取余数; sign(n) -- 判断n的符号;

floor(n) -- 取小于等于n的正整数; ceil() -- 取大于等于n的正整数;

round(n,integer) -- 对n四舍五入,保留位数为integer; trunc(n,integer) -- 对n截取,截取保留的位数为integer;

covert(char,dest_sest,source_set) -- 字符集转换,例:convert(username, 'ZHS16GBK','UTF8');

cast(expr as type_name) -- 数据类型转换,常用于数字与字符间转换,例:cast(id_no as varchar);

部分函数的使用简析:

(1)coalesce(COL1,COL2,COL3):返回参数中第一个非null字段值

例如:coalesce(COL1,0):如果COL1为null或‘',则返回默认值0;否则返回COL1的值;

(2)extract(date):对日期特定部分提取(oracle和postgresql使用一致)

例如:

extract(year from now());>>>2018 

extract(month from now());>>>9

extract(month from timestamp '2018-09-10 13:59:59');>>>9

(3)对时间截取trunc()和date_trunc()

>>oracle--trunc()的用法:

trunc(sysdate,'yyyy');//返回当前年的第一天>>>2018-01-01
trunc(sysdate, 'mm');//返回当前月的第一天>>>2018-09-01
trunc(sysdate, 'dd');//返回当前时间的年月日>>>2018-09-14
trunc(sysdate, 'hh');//返回当前小时>>>2018-09-14 13:30:50

>>postgreSQL--date_trunc()用法:

date_trunc('year',now());//返回当前时间年的第一天>>>2018-01-01 00:00:00
date_trunc('month',now());//返回当前月的第一天>>2018-09-01 00:00:00
date_trunc('day',now()); //返回当前时间的年月日>>2018-09-14 00:00:00
date_trunc('second',now()); //返回当前时间的年月日时分秒>>2018-09-14 13:30:50 

(3)条件判断

Oracle:
 Select DECODE (payments_info,'CR','Credit','DB','Debit', null) FROM dual;
PostgreSQL:
 Select CASE
 WHEN foo = 'CR' THEN 'Credit'
 WHEN foo = 'DB' THEN 'Debit'
 ELSE 'default'
 END
 FROM t2;

3、DDL语法差异

oracle和pgSQL操作表结构语法基本一致:

修改表名:alter table tbl_user rename tbl_user2;

添加约束:alter table 表名 add constraint 表名_列名_nn check (is not null)

添加列:alter table tbl_user add age number(3) default 18 not null;

alter table tbl_user add age number(3) default 18 not null after sex;(在指定列后添加列)

删除列:alter table tbl_user drop column age;

修改列:alter table tbl_user modify password default'000000' not null;(修改约束)

修改列名:alter table tbl_user rename column password to pwd;

只有更改列的数据类型写法有些差异

Oracle:ALTER TABLE table_name modify column_name datatype;

PostgreSQL:ALTER TABLE table_name ALTER column_name TYPE datatype;

4、DML语法差异

oracle和pgSQL增删改查语法基本一致,只有upsert有差异

Oracle:有自带的merge into功能(一个强大的操作)

PostgreSQL:不支持merge操作,可以使用on conflict() do

例:

insert into TargetTable

   select id,desc

   from SourceTable

 on conflict (id)

 do update set

   desc = exclude.desc

5、查询语句差异

(1)查询表中最新n条数据(Oracle有rownum,postgreSQL有limit)

postgreSQL:

select * from olc.olc_member_intebid_info order by create_time desc limit n;

注意:limit必须用于 order by 之后

Oracle:

写法一:

select t.* from (select * from nwd.tc_inte_bid_record order by create_time desc) t where rownum <= n;

写法二:

select * from(select t.*, row_number() over(order by create_time desc) rn from nwd.tc_inte_bid_record t) where rn <=n;

上述写法一为通用常规写法;写法二可以对分组后数据排序,分组语句写在over()中

(2)子查询

postgresql子查询要求比较严格,必须具有别名才可以

6、 Postgresql命令行常用操作(psql)

psql -d dbname -U username -p 5210 -h 172.0.0.1

--password 's&cws123'

如果不想输入密码,可以在.pgpass隐藏文件中添加密码,格式:

172.0.0.1:5210:dbname:username:password

注意.pgpass的权限问题:chmod 0600 ~/.pgpass

-- 查询某个库下的所有表(\dt)
select * from pg_tables where schemaname = 'idn_dw';

-- 查询某个存储过程(\df)
select proname,prosrc from pg_proc where proname = 'func_dwd_customer_info';

-- 查询某个表下的字段(\d tablen_ame)
select table_schema,table_name,t.colname,string_agg(column_name,',') as COLS
from information_schema.columns
LEFT JOIN (select pg_class.relname as tablename,pg_attribute.attname as colname 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 = pg_constraint.conkey[1]
where pg_constraint.contype='p') t
on table_name=t.tablename
where TABLE_NAME = 's10_anfd_rule'
group by table_schema,table_name,t.colname;

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。如有错误或未考虑完全的地方,望不吝赐教。

(0)

相关推荐

  • 解决postgreSql 将Varchar类型字段修改为Int类型报错的问题

    项目使用postgreSql数据库,先需要将库中的某个表中的某个字段类型由Varchar改成Int,直接右键设计表,修改类型为int,保存的时候报错,错误如下: 意思就是,这个crt_user字段不能自动转换成成类型bigint,需要使用USING表达式来转换. 这是在库中运行修改字段的类型的sql: ALTER TABLE auth_client_service ALTER COLUMN crt_user SET DATA TYPE int8 USING crt_user:: int8, AL

  • postgresql 修改列类型操作

    习惯了Oracle中: ALTER TABLE 表名 ALTER COLUMN 列名 新的数据类型[(长度)] NULL或NOT NULL 这种修改方式的时候,在pg中: highgo=# create table p1 (id int,pswd varchar(30),time timestamp); CREATE TABLE highgo=# insert into p1 select generate_series(1,500000),md5('random()::text'),clock

  • PostgreSQL 修改表字段常用命令操作

    --数据库.模式.表名 "identities"."Test"."tab_test" --修改字段名 ALTER TABLE "identities"."Test"."tab_test" RENAME "u_name" to realname ; --添加字段 ALTER TABLE "identities"."Test".&q

  • PostgreSQL 中字段类型varchar的用法

    PostgreSql数据库中varchar类型与sql server中字段用法有差别,PostgreSql中如果字段设置为varchar类型长度为10,则无论存字母.数字或其它符号,长度最大为10个,也就是字母和汉字占的位置是一样的. Sql server中如设置字段类型为nvarchar类型长度为10,则存汉字最大为5个,字母为10个,字母加汉字混合时,字母和汉字占的长度一样 补充:Postgresql 数据库 varchar()字符占用多少字节 如下所示: create table tmp1

  • 浅谈postgresql数据库varchar、char、text的比较

    如下所示: 名字 描述 character varying(n), varchar(n) 变长,有长度限制 character(n), char(n) 定长,不足补空白 text 变长,无长度限制 简单来说,varchar的长度可变,而char的长度不可变,对于postgresql数据库来说varchar和char的区别仅仅在于前者是变长,而后者是定长,最大长度都是10485760(1GB) varchar不指定长度,可以存储最大长度(1GB)的字符串,而char不指定长度,默认则为1,这点需要

  • PostgreSQL 如何修改文本类型字段的存储方式

    PostgreSQL存储方式分为以下4种: PLAIN避免压缩或者线外存储:而且它禁用变长类型的单字节头部.这是不可TOAST数据类型列的唯一可能的策略.只是对那些不能TOAST的数据类型才有可能. EXTENDED允许压缩和线外存储.这是大多数可TOAST数据类型的默认策略. 首先将尝试进行压缩,如果行仍然太大,那么则进行线外存储. EXTERNAL允许线外存储,但是不许压缩.使用EXTERNAL将令那些在宽text和 bytea列上的子串操作更快(代价是增加了存储空间), 因此这些操作被优化

  • 基于PostgreSQL和mysql数据类型对比兼容

    1.数值类型 整数: mysql中的整数类型和pg相比,两者有以下区别: mysql:mysql中支持int 1,2,3,4,8 字节,同时支持有符号,无符号.并且mysql中支持在数值列中指定zerofill,用来将存储的数值通过填充0的方式达到指定数据类型的长度(mysql8开始不建议使用ZEROFILL属性,并且在将来的MySQL版本中将不再支持该属性). pg:pg支持 int 2,4,8 字节,且数值都是有符号的. mysql整数类型: pg整数类型: 那么对于mysql中的1,3字节

  • PostgreSQL中json数据类型详解

    目录 前言 一.PG数据库中JSON的类型 1.json和jsonb的区别 2.项目开发中的选择 3.json数据类型 二.PG中json的简单操作 1.基础json数据操作 2.json和jsonb输出对比 3.jsonb包含测试 总结 前言 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式.它基于 ECMAScript(European Computer Manufacturers Association, 欧洲计算机协会制定的js规范)的一个子集,

  • 基于PostgreSQL/openGauss 的分布式数据库解决方案

    在 MySQL ShardingSphere-Proxy 逐渐成熟并被广泛采用的同时,ShardingSphere 团队也在 PostgreSQL ShardingSphere-Proxy 上持续发力.相比前期的 alpha 与 beta,5.0.0 正式版对 PostgreSQL 的协议实现.SQL 支持度.权限控制等方面进行了大量的完善,为后续全面对接 PostgreSQL 生态打下基础.ShardingSphere-Proxy 与 PostgreSQL 的生态对接,让用户能够在 Postg

  • PostgreSQL使用MySQL作为外部表(mysql_fdw)

    目录 下载安装 使用示例 配置参数 PostgreSQL 提供了一种访问和操作外部数据源的机制,称为外部数据包装器(Foreign Data Wrapper).利用这种外部数据管理机制,我们可以在 PostgreSQL 中访问各种同构数据库(PostgreSQL).异构数据库(MySQL.Oracle.SQL Server.SQLite.HBase.Cassandra.ClickHouse.CouchDB.MongoDB.Neo4j.Redis.Hadoop.HIve等)以及文本文件(CSV.J

  • 基于PHP和Mysql相结合使用jqGrid读取数据并显示

    jqGrid可以动态读取和加载外部数据,本文将结合PHP和Mysql给大家讲解如何使用jqGrid读取数据并显示,以及可以通过输入关键字查询数据的ajax交互过程. 下面给大家展示效果图,喜欢的朋友可以阅读全文哦. jqGrid本身带有search和edit表格模块,但是这些模块会使得整个插件体积显得有点庞大,而且笔者认为jqGrid的搜索查询和编辑/添加功能不好用,所以笔者放弃jqGrid自有的search和edit表格模块,借助jquery利器来完成相关功能,符合项目的实际应用. XHTML

  • 三种常用的MySQL 数据类型

    MySQL中定义数据字段的类型对你数据库的优化是非常重要的. MySQL支持多种类型,大致可以分为三类:数值.日期/时间和字符串(字符)类型. 数值类型 MySQL支持所有标准SQL数值数据类型. 这些类型包括严格数值数据类型(INTEGER.SMALLINT.DECIMAL和NUMERIC),以及近似数值数据类型(FLOAT.REAL和DOUBLE PRECISION). 关键字INT是INTEGER的同义词,关键字DEC是DECIMAL的同义词. BIT数据类型保存位字段值,并且支持MyIS

  • MySQL 数据类型选择原则

    小而美 通常来说,尽可能使用占用存储空间小的数据类型来存储数据.这类数据类型通常也会更快,并且占用的磁盘空间.内存乃至缓存都更小,而且占用的 CPU 处理周期也少. 但是,务必准确估计要存储的数据值的范围.因为在数据表结构的多个地方扩充数据范围会是一个痛苦且耗时的过程.如果在犹豫哪种数据类型合适,那就选择你认为不会超出范围的最小空间的类型(在系统早期或者数据表 数据不多的情况下也可以进行调整). 简单至上 数据类型越简单意味着处理数据的 CPU 周期越少.例如,整型相比字符型而言,处理起来更容易

  • 详解MySQL数据类型DECIMAL(N,M)中N和M分别表示的含义

    同事问MySQL数据类型DECIMAL(N,M)中N和M分别表示什么含义,M不用说,显然是小数点后的小数位数,但这个N究竟是小数点之前的最大位数,还是加上小数部分后的最大位数?这个还真记不清了.于是乎,创建测试表验证了一番,结果如下: 测试表,seller_cost字段定义为decimal(14,2) CREATE TABLE `test_decimal` ( `id` int(11) NOT NULL, `seller_cost` decimal(14,2) DEFAULT NULL ) EN

  • MySQL数据类型中DECIMAL的用法实例详解

    MySQL数据类型中DECIMAL的用法实例详解 在MySQL数据类型中,例如INT,FLOAT,DOUBLE,CHAR,DECIMAL等,它们都有各自的作用,下面我们就主要来介绍一下MySQL数据类型中的DECIMAL类型的作用和用法. 一般赋予浮点列的值被四舍五入到这个列所指定的十进制数.如果在一个FLOAT(8, 1)的列中存储1. 2 3 4 5 6,则结果为1. 2.如果将相同的值存入FLOAT(8, 4) 的列中,则结果为1. 2 3 4 6. 这表示应该定义具有足够位数的浮点列以便

  • Java基于jdbc连接mysql数据库操作示例

    本文实例讲述了Java基于jdbc连接mysql数据库操作.分享给大家供大家参考,具体如下: import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class MySQLDemo { private Connection conn = null; pri

随机推荐