连接服务器
psql -h hostname -p port -U username -W dbname
[tony@sqlhost ~]> psql -h 192.168.56.104 -p 5432 -U tony hrdb
Password for user tony:
psql (12.4)
Type "help" for help.
hrdb=>
查看帮助
hrdb=> help
You are using psql, the command-line interface to PostgreSQL.
Type: \copyright for distribution terms
\h for help with SQL commands
\? for help with psql commands
\g or terminate with semicolon to execute query
\q to quit
hrdb=> \?
General
\copyright show PostgreSQL usage and distribution terms
\crosstabview [COLUMNS] execute query and display results in crosstab
\errverbose show most recent error message at maximum verbosity
\g [FILE] or ; execute query (and send results to file or |pipe)
\gdesc describe result of query, without executing it
\gexec execute query, then execute each value in its result
\gset [PREFIX] execute query and store results in psql variables
\gx [FILE] as \g, but forces expanded output mode
\q quit psql
\watch [SEC] execute query every SEC seconds
Help
\? [commands] show help on backslash commands
\? options show help on psql command-line options
\? variables show help on special variables
\h [NAME] help on syntax of SQL commands, * for all commands
...
hrdb=> \h
Available help:
ABORT CREATE FOREIGN DATA WRAPPER DROP ROUTINE
ALTER AGGREGATE CREATE FOREIGN TABLE DROP RULE
ALTER COLLATION CREATE FUNCTION DROP SCHEMA
ALTER CONVERSION CREATE GROUP DROP SEQUENCE
ALTER DATABASE CREATE INDEX DROP SERVER
ALTER DEFAULT PRIVILEGES CREATE LANGUAGE DROP STATISTICS
...
hrdb=> \h insert
Command: INSERT
Description: create new rows in a table
Syntax:
[ WITH [ RECURSIVE ] with_query [, ...] ]
INSERT INTO table_name [ AS alias ] [ ( column_name [, ...] ) ]
[ OVERRIDING { SYSTEM | USER } VALUE ]
{ DEFAULT VALUES | VALUES ( { expression | DEFAULT } [, ...] ) [, ...] | query }
[ ON CONFLICT [ conflict_target ] conflict_action ]
[ RETURNING * | output_expression [ [ AS ] output_name ] [, ...] ]
where conflict_target can be one of:
( { index_column_name | ( index_expression ) } [ COLLATE collation ] [ opclass ] [, ...] ) [ WHERE index_predicate ]
ON CONSTRAINT constraint_name
and conflict_action is one of:
DO NOTHING
DO UPDATE SET { column_name = { expression | DEFAULT } |
( column_name [, ...] ) = [ ROW ] ( { expression | DEFAULT } [, ...] ) |
( column_name [, ...] ) = ( sub-SELECT )
} [, ...]
[ WHERE condition ]
URL: https://www.postgresql.org/docs/12/sql-insert.html
查看连接
hrdb=> \conninfo
You are connected to database "hrdb" as user "tony" on host "192.168.56.104" at port "5432".
hrdb=> SELECT datname, pid, usename, client_addr, wait_event, state, backend_type
hrdb-> FROM pg_catalog.pg_stat_activity;
datname | pid | usename | client_addr | wait_event | state | backend_type
----------+-------+----------+--------------+---------------------+--------+------------------------------
| 1734 | | | AutoVacuumMain | | autovacuum launcher
| 1736 | postgres | | LogicalLauncherMain | | logical replication launcher
postgres | 27031 | postgres | | | active | client backend
hrdb | 27898 | postgres | 192.168.56.1 | ClientRead | idle | client backend
hrdb | 27900 | postgres | 192.168.56.1 | ClientRead | idle | client backend
hrdb | 27902 | postgres | 192.168.56.1 | ClientRead | idle | client backend
| 1732 | | | BgWriterHibernate | | background writer
| 1731 | | | CheckpointerMain | | checkpointer
| 1733 | | | WalWriterMain | | walwriter
(9 rows)
SELECT pg_cancel_backend(pid);
SELECT pg_terminate_backend(pid);
查看版本
hrdb=> SELECT version();
version
---------------------------------------------------------------------------------------------------------
PostgreSQL 12.4 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-39), 64-bit
(1 row)
配置参数
SHOW name
SHOW ALL
hrdb=> show shared_buffers;
shared_buffers
----------------
256MB
(1 row)
SET [ SESSION | LOCAL ] configuration_parameter { TO | = } { value | 'value' | DEFAULT }
SELECT pg_reload_conf();
退出客户端
postgres=# \q
[root@sqlhost ~]#
角色、用户和组
创建角色
CREATE ROLE role_name [ [ WITH ] option [ ... ] ]
option:
SUPERUSER | NOSUPERUSER
| CREATEDB | NOCREATEDB
| CREATEROLE | NOCREATEROLE
| INHERIT | NOINHERIT
| LOGIN | NOLOGIN
| REPLICATION | NOREPLICATION
| BYPASSRLS | NOBYPASSRLS
| CONNECTION LIMIT connlimit
| [ ENCRYPTED ] PASSWORD 'password' | PASSWORD NULL
| VALID UNTIL 'timestamp'
| IN ROLE role_name [, ...]
| IN GROUP role_name [, ...]
| ROLE role_name [, ...]
| ADMIN role_name [, ...]
| USER role_name [, ...]
| SYSID uid
CREATE ROLE tony LOGIN PASSWORD 'Pswd#123';
CREATE GROUP tony LOGIN PASSWORD 'Pswd#123';
CREATE USER tony PASSWORD 'Pswd#123';
ALTER ROLE tony createdb;
ALTER USER tony createdb;
查看角色
SELECT rolname, rolsuper, rolcanlogin
FROM pg_catalog.pg_roles;
rolname |rolsuper|rolcanlogin|
-------------------------|--------|-----------|
pg_monitor |false |false |
pg_read_all_settings |false |false |
pg_read_all_stats |false |false |
pg_stat_scan_tables |false |false |
pg_read_server_files |false |false |
pg_write_server_files |false |false |
pg_execute_server_program|false |false |
pg_signal_backend |false |false |
postgres |true |true |
monitor_system_stats |false |false |
tony |false |true |
SELECT current_user;
current_user|
------------|
postgres |
修改密码
ALTER ROLE tony PASSWORD 'Pswd123@';
ALTER USER tony PASSWORD 'Pswd123@';
设置密码失效时间
ALTER ROLE tony VALID UNTIL '2020-12-12 00:00:00';
ALTER USER tony VALID UNTIL 'infinity';
用户授权
GRANT privilege_list | ALL
ON [ TABLE ] table_name
TO role_name;
GRANT SELECT, INSERT, UPDATE, DELETE
ON employees, departments, jobs
TO tony;
GRANT monitor_system_stats TO tony;
ALTER GROUP monitor_system_stats ADD USER tony;
查看权限
SELECT table_catalog, table_schema, table_name, privilege_type
FROM information_schema.role_table_grants
WHERE grantee = 'tony';
table_catalog|table_schema|table_name |privilege_type|
-------------|------------|-----------------|--------------|
hrdb |public |employees |INSERT |
hrdb |public |employees |SELECT |
hrdb |public |employees |UPDATE |
hrdb |public |employees |DELETE |
...
撤销权限
REVOKE privilege_list | ALL
ON TABLE table_name
FROM role_name;
REVOKE SELECT, INSERT, UPDATE, DELETE
ON employees, departments, jobs
FROM tony;
REVOKE monitor_system_stats
FROM tony;
ALTER GROUP monitor_system_stats DROP USER tony;
设置当前角色
SELECT session_user, current_user;
session_user|current_user|
------------|------------|
postgres |postgres |
SET ROLE tony;
SELECT session_user, current_user;
session_user|current_user|
------------|------------|
postgres |tony |
SET ROLE NONE;
RESET ROLE;
删除角色
DROP ROLE IF EXISTS tony;
数据库和模式
查看数据库
postgres=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-----------+----------+----------+-------------+-------------+-----------------------
ds2 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
hrdb | tony | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
pagila | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
template0 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
(6 rows)
SELECT datname
FROM pg_catalog.pg_database;
datname |
---------|
postgres |
template1|
template0|
pagila |
ds2 |
hrdb |
创建数据库
CREATE DATABASE db_name
[ [ WITH ] [ OWNER [=] user_name ]
[ TEMPLATE [=] template ]
[ ENCODING [=] encoding ]
[ LC_COLLATE [=] lc_collate ]
[ LC_CTYPE [=] lc_ctype ]
[ TABLESPACE [=] tablespace_name ]
[ ALLOW_CONNECTIONS [=] allowconn ]
[ CONNECTION LIMIT [=] connlimit ]
[ IS_TEMPLATE [=] istemplate ] ]
CREATE DATABASE testdb;
修改数据库
ALTER DATABASE db_name RENAME TO new_name
ALTER DATABASE db_name OWNER TO { new_owner | CURRENT_USER | SESSION_USER }
ALTER DATABASE db_name SET TABLESPACE new_tablespace
ALTER DATABASE db_name [ [ WITH ] option [ ... ] ]
option:
ALLOW_CONNECTIONS allowconn
CONNECTION LIMIT connlimit
IS_TEMPLATE istemplate
ALTER DATABASE testdb RENAME TO newdb;
ALTER DATABASE db_name SET configuration_parameter { TO | = } { value | DEFAULT }
ALTER DATABASE db_name RESET configuration_parameter
ALTER DATABASE newdb SET enable_indexscan TO off;
删除数据库
DROP DATABASE [IF EXISTS] db_name;
DROP DATABASE newdb;
查看模式
CREATE DATABASE testdb;
postgres=# \c testdb;
You are now connected to database "testdb" as user "postgres".
testdb=# \dn
List of schemas
Name | Owner
--------+----------
public | postgres
(1 row)
SELECT *
FROM pg_catalog.pg_namespace;
oid |nspname |nspowner|nspacl |
-----|------------------|--------|-----------------------------------|
99|pg_toast | 10|NULL |
12314|pg_temp_1 | 10|NULL |
12315|pg_toast_temp_1 | 10|NULL |
11|pg_catalog | 10|{postgres=UC/postgres,=U/postgres} |
2200|public | 10|{postgres=UC/postgres,=UC/postgres}|
13887|information_schema| 10|{postgres=UC/postgres,=U/postgres} |
创建模式
CREATE SCHEMA IF NOT EXISTS schema_name [ AUTHORIZATION role_name ]
CREATE SCHEMA app AUTHORIZATION tony;
修改模式
ALTER SCHEMA schema_name RENAME TO new_name
ALTER SCHEMA schema_name OWNER TO new_owner
ALTER SCHEMA app RENAME TO sale;
模式搜索路径
SELECT count(*) FROM hrdb.public.employees;
show search_path;
search_path
-----------------
"$user", public
(1 row)
SET search_path TO sale,public;
删除模式
DROP SCHEMA [ IF EXISTS ] schema_name [ CASCADE | RESTRICT ]
DROP SCHEMA sale;
管理数据表
创建表
CREATE TABLE [ IF NOT EXISTS ] table_name
(
column_name data_type column_constraint,
column_name data_type,
...,
table_constraint
);
CREATE TABLE departments
( department_id INTEGER NOT NULL PRIMARY KEY
, department_name CHARACTER VARYING(30) NOT NULL
) ;
CREATE TABLE employees
( employee_id INTEGER NOT NULL
, first_name CHARACTER VARYING(20)
, last_name CHARACTER VARYING(25) NOT NULL
, email CHARACTER VARYING(25) NOT NULL
, phone_number CHARACTER VARYING(20)
, hire_date DATE NOT NULL
, salary NUMERIC(8,2)
, commission_pct NUMERIC(2,2)
, manager_id INTEGER
, department_id INTEGER
, CONSTRAINT emp_emp_id_pk
PRIMARY KEY (employee_id)
, CONSTRAINT emp_salary_min
CHECK (salary > 0)
, CONSTRAINT emp_email_uk
UNIQUE (email)
, CONSTRAINT emp_dept_fk
FOREIGN KEY (department_id)
REFERENCES departments(department_id)
, CONSTRAINT emp_manager_fk
FOREIGN KEY (manager_id)
REFERENCES employees(employee_id)
) ;
CREATE TABLE [ IF NOT EXISTS ] table_name
AS query
[ WITH [ NO ] DATA ];
CREATE TABLE emp1
AS
SELECT *
FROM employees;
查看所有表
testdb=# \d
List of relations
Schema | Name | Type | Owner
--------+-------------+-------+----------
public | departments | table | postgres
public | emp1 | table | postgres
public | employees | table | postgres
(3 rows)
SELECT table_schema, table_name
FROM information_schema.tables
WHERE table_type = 'BASE TABLE';
查看表结构
testdb=# \d employees
Table "public.employees"
Column | Type | Collation | Nullable | Default
----------------+-----------------------+-----------+----------+---------
employee_id | integer | | not null |
first_name | character varying(20) | | |
last_name | character varying(25) | | not null |
email | character varying(25) | | not null |
phone_number | character varying(20) | | |
hire_date | date | | not null |
salary | numeric(8,2) | | |
commission_pct | numeric(2,2) | | |
manager_id | integer | | |
department_id | integer | | |
Indexes:
"emp_emp_id_pk" PRIMARY KEY, btree (employee_id)
"emp_email_uk" UNIQUE CONSTRAINT, btree (email)
Check constraints:
"emp_salary_min" CHECK (salary > 0::numeric)
Foreign-key constraints:
"emp_dept_fk" FOREIGN KEY (department_id) REFERENCES departments(department_id)
"emp_manager_fk" FOREIGN KEY (manager_id) REFERENCES employees(employee_id)
Referenced by:
TABLE "employees" CONSTRAINT "emp_manager_fk" FOREIGN KEY (manager_id) REFERENCES employees(employee_id)
增加字段
ALTER TABLE table_name
ADD COLUMN column_name data_type column_constraint;
ALTER TABLE employees ADD COLUMN description varchar(100);
修改字段
ALTER TABLE employees ALTER COLUMN description SET DEFAULT 'No description';
ALTER TABLE employees ALTER COLUMN description TYPE text;
重命名字段
ALTER TABLE employees
RENAME COLUMN description TO notes;
删除字段
ALTER TABLE employees DROP COLUMN IF EXISTS notes;
增加约束
ALTER TABLE table_name ADD table_constraint;
ALTER TABLE table_name ALTER COLUMN column_name SET DEFAULT expression;
ALTER TABLE table_name ALTER COLUMN column_name SET NOT NULL;
删除约束
ALTER TABLE table_name DROP CONSTRAINT IF EXISTS constraint_name [ RESTRICT | CASCADE ];
ALTER TABLE table_name ALTER COLUMN column_name DROP DEFAULT;
ALTER TABLE table_name ALTER COLUMN column_name DROP NOT NULL;
重命名表
ALTER TABLE [ IF EXISTS ] table_name
RENAME TO new_name;
删除表
DROP TABLE [ IF EXISTS ] table_name [, ...] [ CASCADE | RESTRICT ]
索引
创建索引
CREATE INDEX index_name ON table_name
[USING method]
(column_name [ASC | DESC] [NULLS FIRST | NULLS LAST], ...);
查看索引
SELECT * FROM pg_catalog.pg_indexes;
维护索引
ALTER INDEX index_name RENAME TO new_name;
ALTER INDEX index_name SET TABLESPACE tablespace_name;
REINDEX [ ( VERBOSE ) ] { INDEX | TABLE | SCHEMA | DATABASE | SYSTEM } index_name;
删除索引
DROP INDEX IF EXISTS index_name [ CASCADE | RESTRICT ];
管理表空间
创建表空间
CREATE TABLESPACE tablespace_name
OWNER user_name
LOCATION 'directory';
查看表空间
SELECT * FROM pg_catalog.pg_tablespace;
修改表空间
ALTER TABLESPACE tablespace_name RENAME TO new_name;
ALTER TABLESPACE tablespace_name OWNER TO new_owner;
ALTER TABLESPACE tablespace_name SET ( tablespace_option = value [, ... ] );
ALTER TABLESPACE tablespace_name RESET ( tablespace_option [, ... ] );
删除表空间
DROP TABLESPACE [ IF EXISTS ] tablespace_name;
备份与还原
使用 pg_dump 执行逻辑备份
pg_dump db_name > file_name.sql
pg_dump -t 'table_name*' db_name > file_name.sql
pg_dump -Fc db_name -f file_name.dmp
pg_dump -Fd db_name -f file_dir
pg_dump -Ft db_name -f file_name.tar
使用 psql/pg_restore 执行还原
psql newdb -f file_name.sql
pg_dump -h host1 db_name | psql -h host2 db_name
pg_restore -d newdb file_name.dmp
pg_restore -d newdb file_dir
pg_restore -d newdb file_name.tar
备份/还原整个数据库集群
pg_dumpall -f cluster.sql
psql -f cluster.sql postgres
使用 COPY 导入/导出表数据
COPY table_name
FROM { 'filename' | PROGRAM 'command' | STDIN }
[ [ WITH ] ( option [, ...] ) ]
[ WHERE condition ]
COPY { table_name | ( query ) }
TO { 'filename' | PROGRAM 'command' | STDOUT }
[ [ WITH ] ( option [, ...] ) ]
查询语句
单表查询
SELECT column1, column2, ...
FROM table_name;
SELECT * FROM table_name;
SELECT DISTINCT column1, column2, ...
FROM table_name;
查询条件
SELECT column1, column2, ...
FROM table
WHERE conditions;
expr LIKE pattern [ESCAPE escape_character]
SELECT first_name,
last_name
FROM employees
WHERE last_name LIKE 'Kin%';
first_name | last_name
------------+-----------
Steven | King
Janette | King
(2 rows)
排序显示
SELECT column1, column2, ...
FROM table_name
ORDER BY column1 ASC, column2 DESC, ...;
限定数量
SELECT column1, column2, ...
FROM table_name
[WHERE conditions]
[ORDER BY column1 ASC, column2 DESC, ...]
[OFFSET m {ROW | ROWS}]
[FETCH { FIRST | NEXT } [ num_rows] { ROW | ROWS } ONLY];
SELECT column1, column2, ...
FROM table_name
[WHERE conditions]
[ORDER BY column1 ASC, column2 DESC, ...]
[LIMIT { num_rows| ALL } ]
[OFFSET m {ROW | ROWS}];
分组操作
SELECT column1, column2, agg_func()
FROM table_name
GROUP BY column1, column2
HAVING conditions;
多表连接
SELECT t1.column1, t2.column2, ...
FROM table1 AS t1
[INNER | LEFT | RIGHT | FULL | CROSS] JOIN table2 AS t2
ON conditions;
子查询
SELECT column1, column2, ...
FROM (subquery) AS table_alias;
SELECT table1.colum1, t2.col1, ...
FROM table1
JOIN LATERAL (
SELECT ...
FROM table2
WHERE table1.col1 = table1.column1) t2;
SELECT table1.column1, table1.column12, ...
FROM table1
WHERE EXISTS ( SELECT 1
FROM table2
WHERE table2.col1 = table1.col1);
集合运算
SELECT column1, column2
FROM table1
UNION [DISTINCT | ALL]
SELECT col1, col2
FROM table2;
SELECT column1, column2
FROM table1
INTERSECT [DISTINCT | ALL]
SELECT col1, col2
FROM table2;
SELECT column1, column2
FROM table1
EXCEPT [DISTINCT | ALL]
SELECT col1, col2
FROM table2;
通用表表达式
WITH cte_name (col1, col2, ...) AS (
cte_query_definition
)
sql_statement;
WITH RECURSIVE cte(n) AS (
SELECT 1 AS n -- 初始查询
UNION ALL
SELECT n+1 FROM cte WHERE n < 10) -- 递归查询
SELECT * FROM cte;
DML 语句
插入数据
INSERT INTO table_name(column1, column2, ...)
VALUES (value1, value2, ...);
INSERT INTO table_name(column1, column2, ...)
VALUES (val11,val12,...), (val21,val22,...), (val31,val32,...);
INSERT INTO table_name(column1, column2, ...)
SELECT ...;
INSERT INTO table_name(column1, column2, ...)
...
RETUNRING ...;
更新数据
UPDATE table_name
SET column1 = value1,
column2 = value2,
...
WHERE conditions;
UPDATE table1
SET column1 = table2.salary,
column2 = value2,
...
FROM table2
WHERE conditions;
UPDATE table_name
SET ...
WHERE conditions
RETURNING ...;
删除数据
DELETE FROM table_name
WHERE conditions;
DELETE
FROM table1
USING table2
WHERE conditions;
DELETE FROM table_name
WHERE conditions
RETURNING ...;
TRUNCATE TABLE table_name;
合并数据
INSERT INTO table_name(column1, column2, ...)
...
ON CONFLICT [conflict_target]
{DO NOTHING | DO UPDATE SET ... [WHERE contidions]};
事务控制
开始事务
BEGIN;
提交事务
COMMIT;
回滚事务
ROLLBACK;
事务保存点
BEGIN;
...
SAVEPOINT savepoint_name;
...
ROLLBACK TO SAVEPOINT savepoint_name;
...
COMMIT;
隔离级别
SHOW transaction_isolation;
BEGIN;
SET TRANSACTION ISOLATION LEVEL { SERIALIZABLE | REPEATABLE READ | READ COMMITTED | READ UNCOMMITTED };
...
视图
创建视图
CREATE [OR REPLACE] VIEW view_name
AS
select-statement
WITH CHECK OPTION;
查看所有视图
SELECT *
FROM information_schema.views;
查看视图定义
SELECT view_definition
FROM information_schema.views
WHERE table_schema = 'public'
AND table_name = 'employees_it';
SELECT employees.employee_id,
employees.first_name,
employees.last_name,
employees.email,
employees.phone_number,
employees.hire_date,
employees.job_id,
employees.manager_id,
employees.department_id
FROM employees
WHERE (employees.department_id = 60);
修改视图
ALTER VIEW IF EXISTS view_name RENAME TO new_name
删除视图
DROP VIEW [IF EXISTS] view_name;
存储过程/函数
创建存储过程/函数
CREATE [ OR REPLACE ] PROCEDURE
procedure_name ( [ [ argmode ] [ argname ] argtype [ { DEFAULT | = } default_expr ] [, ...] ] )
AS $$
DECLARE
declarations
BEGIN
statements;
...
END; $$
LANGUAGE plpgsql;
CREATE [ OR REPLACE ] FUNCTION
function_name ( [ [ argmode ] [ argname ] argtype [ { DEFAULT | = } default_expr ] [, ...] ] )
RETURNS rettype
AS $$
DECLARE
declarations
BEGIN
statements;
...
END; $$
LANGUAGE plpgsql;
调用存储过程/函数
CALL procedure_name( argument1, ... );
SELECT function_name( argument1, ... );
重命名存储过程/函数
ALTER PROCEDURE procedure_name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ]
RENAME TO new_name;
ALTER FUNCTION function_name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ]
RENAME TO new_name;
删除存储过程/函数
DROP PROCEDURE IF EXISTS procedure_name [ CASCADE | RESTRICT ];
DROP FUNCTION IF EXISTS function_name [ CASCADE | RESTRICT ];
触发器
创建触发器
CREATE [ OR REPLACE ] FUNCTION trigger_function ()
RETURNS trigger
AS $$
DECLARE
declarations
BEGIN
statements;
...
END; $$
LANGUAGE plpgsql;
CREATE TRIGGER trigger_name
{BEFORE | AFTER | INSTEAD OF} {event [OR ...]}
ON table_name
[FOR [EACH] {ROW | STATEMENT}]
[WHEN ( condition ) ]
EXECUTE FUNCTION trigger_function;
查看触发器
SELECT *
FROM information_schema.triggers;
修改触发器
ALTER TRIGGER trigger_name ON table_name RENAME TO new_name;
启用/禁用触发器
ALTER TABLE table_name
{ENABLE | DISABLE} TRIGGER {trigger_name | ALL | USER};
删除触发器
DROP TRIGGER [IF EXISTS] trigger_name
ON table_name [RESTRICT | CASCADE];
文章转载自SQL编程思想,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




