Category: SQL

Mybatis 插入或更新数据

在日常的开发中,我们经常会遇到这样的需求,我们有一个存储主数据的表,当有新的数据写入的时候,若库中存在数据则更新,否则当作新的数据写入。

一般情况下,我们会先对数据库进行一次Select,若数据存在我们则执行更新操作,当然这种方法在大部分情况下是可行的,但数据量大或者数据写入频繁的时候,这种方法就表现出来它的不稳定。

其实在数据库中都提供了UNIQUE约束规则,我们可以在数据库中建立UNIQUE约束规则,这样我们在插入具有约束限制数据的时候,我们就会得到一个异常,我们可以捕获这个异常,在异常块中进行更新操作。

在Mysql中我们可以使用更加简单的方式,Mysql提供了这样一个方法on duplicate key update可以让数据库直接搞定数据的插入或更新。

首先在数据库中创建约束

create unique index mytest_uindex on table (fieldA, FieldB);

编写SQL语句

insert into table (fieldA, filedB)) values ('a', 'b') on duplicate key update filedA = a1, fieldB = a2;

这样一波操作下来,你会神奇的发现,原来可以如此简单。。

该方法会删除掉已有数据,再进行插入,具体可以观察数据的自增ID。

具体用法可以查看这里:https://dev.mysql.com/doc/refman/5.7/en/insert-on-duplicate.html

psql connect docker postgresql

方式一、

docker exec -u 0 -it <CONTAINER ID> bash
su postgres
psql -U <DBUSER> -W -d <DBNAME>

# 查看PGSQL默认服务
pstree

方式二、

docker run -it --rm --network docker_odoonetwork postgres psql -h pgsql -U odoo -d analogcircuit

docker-compose.yml

version: '2'
services:
  web:
    image: odoo:12.0
    container_name: odoo
    depends_on:
      - db
    ports:
      - "8069:8069"
    networks:
      - "odoonetwork"
    volumes:
      - odoo-web-data:/var/lib/odoo
      - ./config:/etc/odoo
      - ./addons:/mnt/extra-addons
  db:
    image: postgres:10
    container_name: pgsql
    networks:
      - "odoonetwork"
    environment:
      - POSTGRES_DB=postgres
      - POSTGRES_PASSWORD=odoo
      - POSTGRES_USER=odoo
      - PGDATA=/var/lib/postgresql/data/pgdata
    volumes:
      - odoo-db-data:/var/lib/postgresql/data/pgdata
networks:
  odoonetwork:
    driver: bridge  
volumes:
  odoo-web-data:
  odoo-db-data:

Oracle start with…connect by prior

Oracle中start with…connect by prior子句用法connect by 是结构化查询中用到的,其基本语法是

select column_name from tablename
start with 条件1
connect by 条件2
where 条件3;

简单说来是将一个树状结构存储在一张表里,比如一个表中存在两个字段:org_id,parent_id,那么通过表示每一条记录的parent是谁,就可以形成一个树状结构,用上述语法的查询可以取得这棵树的所有记录。

prior 关键字表示父数据,prior 条件表示子数据需要满足父数据的什么条件。

实际使用

在项目中我们经常用到层级编码,例如:301090213,他其实是一个按照每2个数值分割的一种树形数据结构,在实际使用中我们希望通过301090213这个编码找出它所对应的所有父级数据。

常规情况我们会使用Like关键字来直接查找,这里其实Oracle提供了树形查找的方式。

我们其实可以这样写代码即可

SELECT * invname from
  bd_invcl
  start WITH pk_invcl = 'pk'
  connect by invcode = prior substr(invcode, 0, length(invcode) -2);

拼接字符

SELECT wm_concat(invname) from
   bd_invcl
   start WITH pk_invcl = 'pk'
   connect by invcode = prior substr(invcode, 0, length(invcode) -2);

SQL Between 边界问题

扩展知识

BETWEEN操作符是选取介于两个值之间的数据。这些值可以是数值、文本或者日期。

然而在使用between and限定日期的时候,特别需要注意,在and后的日期是到天的,那么默认为00:00:00。对于大于00:00:00这样的数据是会排除在外的。

这时候就需要将数据进行to_char处理。或者使用>= and <=这样的操作符进行处理。

PostgreSql 常用操作

登陆控制台

psql -U postgres -h localhost -W -d baseName

一、用户和权限管理

# 可以使用 \h CREATE ROLE 查看语法
CREATE ROLE rolename;
CREATE USER username;

# 例子
CREATE USER jalena WITH CREATEDB LOGIN PASSWORD 'jalena';

CREATE USER和CREATE ROLE的区别在于,CREATE USER指令创建的用户默认是有登录权限的,而CREATE ROLE没有。

# 修改用户权限
ALTER USER jalena WITH NOCREATEDB; # 取消数据库创建权限
ALTER USER jalena WITH PASSWORD 'password'; # 修改密码

定义存取权限

# 授予jalena对demo库所有的权限
GRANT ALL PRIVILEGES ON DATABASE demo TO jalena;

# 只授予某个权限
GRANT UPDATE ON DATABASE demo TO jalena;
GRANT SELECT ON ALL TABLES IN SCHEMA PUBLIC TO jalena;

# 特殊符号《ALL》代表所有权限,《PUBLIC》代表所有用户
GRANT ALL ON demo TO jalena; # 赋给用户所有全选
GRANT SELECT ON demo TO PUBLIC; # 将SELECT权限赋予所有用户

二、备份

PostgreSql提供了2个备份命令,分别为pg_dump和pg_dumpall,这种方式可以在数据库正在使用的时候进行完整一致的备份, 并不阻塞其它用户对数据库的访问。

使用说明可以使用pg_dump --help查看。

pg_dump -F c -f <filename.dmp> -C -E UTF-8 -U <DataBaseUser> <DataBaseName>
pg_dumpall -U postgres -F c -c -f all.dmp

三、恢复

CREATE USER jalena WITH CREATEDB PASSWORD 'password';
CREATE DATABASE demo OWNER jalena;
GRANT ALL PRIVILEGES ON DATABASE odam to inspur;

pg_restore -j5 -U <DBUSER> -W -d <DBNAME> -v <FILEPATH>

四、表与文件之间的拷贝

postgresql提供了COPY命令用于表与文件(标准输出、标准输入)之间的相互拷贝,COPY TO由表至文件,COPY FROM由文件至表。

# 将整张表拷贝至标准输出
copy res_users to stdout;

# 将表的部分字段拷贝至标准输出,且输出字段名称,字段间使用','分割
copy res_users(id,login) to stdout delimiter ',' csv header;

# 将查询结果拷贝至标准输出
copy(select id,login from res_users) to stdout delimiter '|' quote '"' csv header;

将标准输入拷贝至表中需要注意几点

  1. 字段间分割符默认使用【Tab】键
  2. 换行使用回车键
  3. 结束使用反斜线加英文标点(\.)
  4. 指定字段顺序,不然会出现错误的赋值
#将标准输入拷贝至表中
copy res_users(id,login) from stdin;
>> 1	login1
>> 2	login2
>> \.

# 从标准输入拷贝至表中,并将标准输入第一行作为字段名,字段分隔符为','
copy res_users(id,login) from stdin delimiter ',' csv header;
>> 1,login1
>> 2,login2
>> \.

以上是表与标准输入、输出之间的相互拷贝,表与文件的拷贝和以上完全相同,只是将标准输入、输出换成文件。需要注意的是

  1. 数据库用户必须有文件所在路径的写权限
  2. 如果表存在中文字符,导出至csv文件时需要设置编码为GBK,否则使用excel打开中文显示乱码
  3. 将文件导入表中时任然需要考虑编码问题
# 将表拷贝至csv文件中
copy res_users to 'D:/res_users.csv' delimiter ',' csv header;

# 以GBK编码拷贝到cvs文件
copy res_users to 'D:/res_users.csv' delimiter ',' csv header encoding  'GBK';
# 将文件导入至表中
copy res_users from 'd:/res_users.csv' delimiter ',' csv header encoding 'GBK';

五、PSQL常用命令

-- 查看所有psql可执行的命令
\?

-- 退出控制台
\q

-- 退出当前执行命令
q

-- 更改当前工作目录
\cd [目录]

-- 从文件中执行命令
\i 文件

-- 列出全部数据库
\l

-- 列出全部序列
\ds

-- 切换当前数据库到指定的数据库
\c [database_name]

-- 显示所有的表
\dt

-- 显示指定的表的结构
\d [table_name]

-- 显示视图
\dv

-- 列出全部用户
\du or \dg

-- 列出当前数据库和连接的信息
\conninfo

-- 修改用户密码
\password uesrname

Postgresql pg_dump: 因为服务器版本不匹配而终止

之前在生产环境部署的Postgresql为9.6版本,但最近在备份数据的时候发现他所使用的客户端居然是9.2的版本。。

# 查看已安装的postgresql程序
yum list installed |grep postgresql

# 查看Yum已安装的源
yum repolist

# 引入postgresql对应版本的源
# http://yum.postgresql.org/repopackages.php
rpm -Uvh https://download.postgresql.org/pub/repos/yum/9.6/redhat/rhel-7-x86_64/pgdg-centos96-9.6-3.noarch.rpm

# 查找需要的版本
yum search postgresql --enablerepo=pgdg96

# 安装对应版本的客户端
yum install -y postgresql96

# 查看执行程序路径
find / -name pg_dump -type f

# 替换低版本
ln -snf /usr/pgsql-9.6/bin/pg_dump /usr/bin/pg_dump

备份命令

su - postgres -c "pg_dump -U odoo -Fc -d Yunshang -f Yunshang.dump"

恢复命令

createdb -U odoo Yunshang
pg_restore -v -U odoo "F:\python\YunShangZhuangShi\Yunshang.dump"

Archives