SQL-CheatSheet

SQL 语法速览与备忘清单

SQL 是 Structrued Query Language 的缩写,即结构化查询语言。它是负责与 ANSI(美国国家标准学会)维护的数据库交互的标准。作为关系数据库的标准语言,它已被众多商用 DBMS 产品所采用,使得它已成为关系数据库领域中一个主流语言,不仅包含数据查询功能,还包括插入、删除、更新和数据定义功能。最为重要的 SQL92 版本的详细标准可以查看这里,或者在 Wiki 上查看 SQL 标准的变化。

  • DDL 是数据定义语言的简称,它涉及到数据库模式和描述,即数据应该如何在数据库中存在。
  • DML 是数据操作语言的简称,它处理数据操作,包括最常见的 SQL 语句,如 SELECT、INSERT、UPDATE、DELETE 等,它被用来存储、修改、检索、删除和更新数据库中的数据。
  • DCL 是数据控制语言的简称,包括 GRANT 等命令,主要涉及数据库系统的权利、权限和其他控制。

数据类型

Text types

数据类型 说明
CHAR(size) 保存一个固定长度的字符串(可以包含字母、数字和特殊字符)。固定的大小在括号中指定。最多可以存储 255 个字符。
VARCHAR(size) 存放一个可变长度的字符串(可以包含字母、数字和特殊字符)。最大的尺寸在括号中指定。最多可以存储 255 个字符。注意:如果你输入一个大于 255 的值,它将被转换成 TEXT 类型。
TINYTEXT 保存一个最大长度为 255 个字符的字符串。
TEXT 保存一个最大长度为 65,535 个字符的字符串。
BLOB 用于 BLOB(二进制大型对象)。最多可以容纳 65,535 个字节的数据 BLOB
MEDIUMTEXT 存储一个最大长度为 16,777,215 个字符的字符串
MEDIUMBLOB 用于 BLOB(二进制大型对象)。最多可以容纳 16,777,215 字节的数据。
LONGTEXT 保存最大长度为 4,294,967,295 个字符的字符串
LONGBLOB 用于 BLOB(二进制大型对象)。最多可以容纳 4,294,967,295 字节的数据。
ENUM(x,y,z,etc.) 让你输入一个可能的值列表。在一个 ENUM 列表中,你最多可以列出 65535 个值。如果插入一个不在列表中的值,将插入一个空白值。注意:值是按照你输入的顺序排序的。你以这种格式输入可能的值。ENUM(‘X’,‘Y’,‘Z’)
SET 与 ENUM 类似,只是 SET 最多可以包含 64 个列表项,并且可以存储多个选择

Number types

数据类型 说明
TINYINT(size) -128 to 127 normal. 0 到 255 UNSIGNED*。可以在括号内指定最大的数字数 SMALLINT(size)
SMALLINT(size) -32768 至 32767 正常。0 至 65535 UNSIGNED*。可以在括号中指定最大的数字数。
MEDIUMINT(size) -8388608 至 8388607 正常。0 至 16777215 UNSIGNED*。可以在括号内指定最大的数字数 INT(size)
INT(size) -2147483648 至 2147483647 正常。0 至 4294967295 UNSIGNED*。可以在括号内指定最大的数字数 BIGINT(size)
BIGINT(size) -9223372036854775808 至 9223372036854775807 正常。0 到 18446744073709551615 UNSIGNED*。可以在括号中指定最大的数字数
FLOAT(size,d) 一个带有浮动小数点的小数字。最大的数字数可以在 size 参数中指定。小数点右边的最大位数可在 d 参数中指定。
DOUBLE(size,d) 一个带有浮动小数点的大数字。可在 size 参数中指定最大位数。小数点右边的最大位数在 d 参数中指定。
DECIMAL(size,d) 一个以字符串形式存储的 DOUBLE,允许使用固定的小数点。最大的数字数可以在 size 参数中指定。小数点右边的最大位数在 d 参数中指定。

Date types

数据类型 说明
DATE() 一个日期。格式。格式:YYYY-MM-DDN 注:支持的范围是'1000-01-01’到'9999-12-31’。
DATETIME() 一个日期和时间的组合。格式。YYYY-MM-DD HH:MI:SSNote: 支持的范围是从'1000-01-01 00:00:00’到'9999-12-31 23:59:59’。
TIMESTAMP() 一个时间戳。TIMESTAMP 值是以 Unix 纪元(‘1970-01-01 00:00:00’UTC)以来的秒数存储。格式。YYYY-MM-DD HH:MI:SSNote: 支持的范围是从'1970-01-01 00:00:01’ UTC 到'2038-01-09 03:14:07’ UTC。

| 时间()|一个时间。格式。HH:MI:SS 注:支持的范围是从’-838:59:59’到'838:59:59’。 | 年份() | 两位数或四位数格式的年份。注:允许四位数格式的数值。1901 至 2155。允许的两位数格式的值。70 至 69,代表 1970 年至 2069 年的年份。

基础语法

-- Comments start with two hyphens. End each command with a semicolon.

-- SQL is not case-sensitive about keywords. The sample commands here
-- follow the convention of spelling them in upper-case because it makes
-- it easier to distinguish them from database, table, and column names.

-- Create and delete a database. Database and table names are case-sensitive.
CREATE DATABASE someDatabase;
DROP DATABASE someDatabase;

-- List available databases.
SHOW DATABASES;

-- Use a particular existing database.
USE employees;

-- Create a table called tablename1, with the two columns shown, for
-- the database currently in use. Lots of other options are available
-- for how you specify the columns, such as their datatypes.

/**
CREATE TABLE <table_name1> (
    <col_name1> <col_type1>,
    <col_name2> <col_type2>,
    <col_name3> <col_type3>
    PRIMARY KEY (<col_name1>),
    FOREIGN KEY (<col_name2>) REFERENCES <table_name2>(<col_name2>)
);
**/
CREATE TABLE tablename1 (fname VARCHAR(20), lname VARCHAR(20));

-- Check if not exit and create
create database if not exists `test`;
USE `test`;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
CREATE TABLE IF NOT EXISTS `tblsample` (

  `id` int(11) NOT NULL auto_increment,
  `recid` int(11) NOT NULL default '0',
  `cvfilename` varchar(250)  NOT NULL default '',
  `cvpagenumber`  int(11) NULL,
  `cilineno` int(11)  NULL,
  `batchname`  varchar(100) NOT NULL default '',
  `type` varchar(20) NOT NULL default '',
  `data` varchar(100) NOT NULL default '',
   PRIMARY KEY  (`id`)

);

IF OBJECT_ID('tbl_kunde', N'U') is not null
	drop table tbl_kunde;
GO
create table tbl_kunde (
  id_kunde int not null primary key,
  fi_moral_nr int,
  name varchar(25) not null,
  vorname varchar not null,
  wohnort varchar
);
GO

-- Insert a row of data into the table tablename1. This assumes that the
-- table has been defined to accept these values as appropriate for it.
INSERT INTO tablename1 VALUES('Richard','Mutt');

-- In tablename1, change the fname value to 'John'
-- for all rows that have an lname value of 'Mutt'.
UPDATE tablename1 SET fname='John' WHERE lname='Mutt';

-- Delete rows from the tablename1 table
-- where the lname value begins with 'M'.
DELETE FROM tablename1 WHERE lname like 'M%';

-- Delete all rows from the tablename1 table, leaving the empty table.
DELETE FROM tablename1;

-- Remove the entire tablename1 table.
DROP TABLE tablename1;

-- Foreign Key
ALTER TABLE tbl_kunde ADD CONSTRAINT FK_fi_moral_nr FOREIGN KEY (fi_moral_nr)
  REFERENCES tkey_moral
  ON UPDATE CASCADE
  ON DELETE SET NULL;

-- Constraint
ALTER TABLE tkey_moral ADD CONSTRAINT PK_id_moral_nr PRIMARY KEY (id_moral_nr);
ALTER TABLE tbl_kunde ADD CONSTRAINT FK_fi_moral_nr FOREIGN KEY (fi_moral_nr)
  REFERENCES tkey_moral
  ON UPDATE CASCADE
  ON DELETE SET NULL;

索引

-- Create
create unique index ix_kund_name on tbl_kunde (name)

-- Disable
alter index ix_kund_name on tbl_kunde disable

-- Rebuild
alter index ix_kund_name on tbl_kunde rebuild

-- Reorganize
alter index ix_kund_name on tbl_kunde reorganize

-- Drop
drop index ix_kund_name on tbl_kunde

-- Alter
drop index ix_kund_name on tbl_kunde

查询

Name Command
Select with regexp in where clause select * from expenses where date regexp '2013-0[4-5]' limit 2;
Select with like in where clause select * from expenses where date like '2013-0%' limit 2;
Select unix timestamp select unix_timestamp(createtime) from expenses limit 1;
Offset limit select * from student limit 4 offset 9
Use replace function UPDATE tb1 SET f1=REPLACE(f1, 'abc', 'def');
Use if function select Db, IF(IFNULL(User, “”)=”“, DB, User) from db;
-- Select all rows and columns from the current database's departments table.
-- Default activity is for the interpreter to scroll the results on your screen.
SELECT * FROM departments;

-- Retrieve all rows from the departments table,
-- but only the dept_no and dept_name columns.
-- Splitting up commands across lines is OK.
SELECT dept_no,
       dept_name FROM departments;

-- Retrieve all departments columns, but just 5 rows.
SELECT * FROM departments LIMIT 5;

-- Retrieve dept_name column values from the departments
-- table where the dept_name value has the substring 'en'.
SELECT dept_name FROM departments WHERE dept_name LIKE '%en%';

-- Retrieve all columns from the departments table where the dept_name
-- column starts with an 'S' and has exactly 4 characters after it.
SELECT * FROM departments WHERE dept_name LIKE 'S____';

-- Select title values from the titles table but don't show duplicates.
SELECT DISTINCT title FROM titles;

-- Same as above, but sorted (case-sensitive) by the title values.
SELECT DISTINCT title FROM titles ORDER BY title;

-- Show the number of rows in the departments table.
SELECT COUNT(*) FROM departments;

-- Show the number of rows in the departments table that
-- have 'en' as a substring of the dept_name value.
SELECT COUNT(*) FROM departments WHERE dept_name LIKE '%en%';

-- A JOIN of information from multiple tables: the titles table shows
-- who had what job titles, by their employee numbers, from what
-- date to what date. Retrieve this information, but instead of the
-- employee number, use the employee number as a cross-reference to
-- the employees table to get each employee's first and last name
-- instead. (And only get 10 rows.)

SELECT employees.first_name, employees.last_name,
       titles.title, titles.from_date, titles.to_date
FROM titles INNER JOIN employees ON
       employees.emp_no = titles.emp_no LIMIT 10;

-- List all the tables in all the databases. Implementations typically provide
-- their own shortcut command to do this with the database currently in use.
SELECT * FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE='BASE TABLE';

-- Sub Query
SELECT DISTINCT course_id
    FROM section
    WHERE semester = Fall AND year= 2009 AND course_id IN (
        SELECT course_id
            FROM section
            WHERE semester = Spring AND year= 2010
    );

联合查询

在一个查询输出中把两个表连接在一起。第三行很重要,因为它显示了这两个表的关系(在本例中是它们的键值)。

SELECT customers.id, customers.name, items.name, customers.state
FROM customers, items
WHERE customers.id=seller_id
ORDER BY customers.id

取 “LEFT “或 “RIGHT “左边的表(本例中为 customers),并加入它,不管它是否有任何值。所以上面的语句显示了所有的用户/客户,即使他们没有销售任何东西。

联合查询

-- Having and without join
select i.dt_name, count(s.dt_stueck_titel) from tbl_stueck as s, tkey_interpret as i
where  s.fi_interpret = i.id_interpret
group by i.dt_name
having count(s.dt_stueck_titel) >10
order by count(s.dt_stueck_titel) de

-- Join the hard way Inner Join
select s.dt_stueck_titel, i.dt_name
from tbl_stueck as s, tkey_interpret as i
where  s.fi_interpret = i.id_interpret
order by s.dt_stueck_titel

-- Multi Join
select sa.id_jahr, st.dt_stueck_titel, ip.dt_name
from tbl_stueck as st, tass_stueck_sampler as ss, tkey_sampler as sa, tkey_interpret as ip
where ss.id_fi_stueck_nr = st.id_stueck_nr
and ss.id_fi_jahr = sa.id_jahr
and  st.fi_interpret = ip.id_interpret
order by  st.dt_stueck_titel

-- Join the right way Inner Equi Key Joining
select dt_stueck_titel, dt_name
from tbl_stueck join tkey_interpret
on fi_interpret = id_interpret
order by dt_stueck_titel

-- Multi Inner Equi Key Joining
select id_fi_jahr, dt_stueck_titel, dt_name
from tbl_stueck
join tass_stueck_sampler on id_fi_stueck_nr = id_stueck_nr
join tkey_interpret on fi_interpret = id_interpret
order by  dt_stueck_titel

子查询

-- Select with Subqueries Select max and min values

select dt_stueck_titel as Titel, dt_zeit as Zeit
from tbl_stueck
where dt_zeit = (select max(dt_zeit) from tbl_stueck)
or dt_zeit = (select min(dt_zeit) from tbl_stueck)
order by dt_zeit;

-- Select with query in condition
select dt_stueck_titel as Titel, dt_zeit as Zeit
from tbl_stueck
where dt_zeit between (select avg(dt_zeit) from tbl_stueck)*0.9
and (select avg(dt_zeit) from tbl_stueck)*1.1
order by dt_zeit;

-- Select query as value
select dt_stueck_titel as Titel,
dt_zeit/(select avg(dt_zeit) from tbl_stueck)*100 as Zeit
from tbl_stueck
where dt_stueck_titel = 'You Shook Me'

-- Union Unify two result sets with a condition
select * from
(select dt_stueck_titel as titel, 'stück' as 'type' from tbl_stueck
union
select dt_name as titel,  'inter' as 'type' from tkey_interpret
union
select dt_stao as titel,  'stao' as 'type' from tkey_standort) as t
where t.titel like '%boy%'

插入与更新

-- Selected fields
INSERT INTO tkey_moral (id_moral_nr, moral_bez) VALUES (1, 'gut'), (2, 'schlecht'), (3, 'schlecht');

-- All fields
INSERT INTO tbl_kunde VALUES (3838,1,'Meier','Laura','Waldibrücke')
INSERT INTO users (first_name, last_name, email, password, location, dept,  is_admin, register_date) values ('Fred', 'Smith', 'fred@gmail.com', '123456', 'New York', 'design', 0, now()), ('Sara', 'Watson', 'sara@gmail.com', '123456', 'New York', 'design', 0, now()),('Will', 'Jackson', 'will@yahoo.com', '123456', 'Rhode Island', 'development', 1, now()),('Paula', 'Johnson', 'paula@yahoo.com', '123456', 'Massachusetts', 'sales', 0, now()),('Tom', 'Spears', 'tom@yahoo.com', '123456', 'Massachusetts', 'sales', 0, now());

-- Update by conditions
UPDATE tbl_kunde SET NAME = 'Menzer' WHERE NAME = 'Waltenspühl-Menzer'
UPDATE tass_police SET praem_stufe = 101 WHERE praem_stufe = 108

-- Delete
delete from tbl_kunde
delete from tkey_moral where id_moral_nr = 4
delete from tbl_kunde where vorname = 'Peter' and name = 'Fischer' or vorname = 'Martin' and name = 'Müller'

MySQL

数据库管理

Name Command
mysql connect mysql -u$username -p$password -P$port -h$dbhost $dbname
database encoding set names utf8;
List databases show databases;
List tables for current db show tables;
Check table definition describe $tablename;
Run sql in non-interactive way =mysql -uUSER -pPASSWORD databasename -e “select * from t limit 10”=
Import db mysql -uUSER -pPASSWORD dbname < backup.sql
export db mysqldump -uUSER -pPASSWORD DATABASE > backup.sql
export db without schema mysqldump -uUSER -pPASSWORD DATABASE --no-data=true --add-drop-table=false > backup.sql
Grant access =GRANT SUPER ON DBNAME.user TO ‘DBUSER’@’%’=
Add column ALTER TABLE expenses ADD COLUMN createtime timestamp not null default now();
Delete Column ALTER TABLE expenses DROP COLUMN createtime;
Delete index DROP INDEX indexname ON table_name;
Create index create index idindex on table_name(col_name) using btree;
Reset password UPDATE mysql.user SET Password=PASSWORD(‘MyNewPass’) WHERE User=’root’; FLUSH PRIVILEGES;
drop user 'braindenny'@'%'; flush privileges; CREATE USER...
CREATE USER 'myuser'@'%' IDENTIFIED BY 'MYPASSWORD';
mysql8 grant privileges to user GRANT ALL PRIVILEGES ON mydbname.* TO 'myuser'@'%' WITH GRANT OPTION;
$ mysql -u root -p

-- Show Users
SELECT User, Host FROM mysql.user;

-- Create User
CREATE USER 'someuser'@'localhost' IDENTIFIED BY 'somepassword';

-- Grant All Priveleges On All Databases
GRANT ALL PRIVILEGES ON * . * TO 'someuser'@'localhost';
FLUSH PRIVILEGES;

-- Show Grants
SHOW GRANTS FOR 'someuser'@'localhost';

-- Remove Grants
REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'someuser'@'localhost';

-- Delete User
DROP USER 'someuser'@'localhost';

时间与日期

-- 今天
select * from 表名 where to_days(时间字段名) = to_days(now());
-- 昨天
SELECT * FROM 表名 WHERE TO_DAYS(NOW()) - TO_DAYS(时间字段名) <= 1
-- 7天
SELECT * FROM 表名 where DATE_SUB(CURDATE(), INTERVAL 7 DAY) <= date(时间字段名)
-- 近30天
SELECT * FROM 表名 where DATE_SUB(CURDATE(), INTERVAL 30 DAY) <= date(时间字段名)
-- 本月
SELECT * FROM 表名 WHERE DATE_FORMAT( 时间字段名, '%Y%m' ) = DATE_FORMAT( CURDATE( ), '%Y%m' )
-- 上一月
SELECT * FROM 表名 WHERE PERIOD_DIFF( date_format( now( ), '%Y%m' ), date_format( 时间字段名, '%Y%m' ) ) =1
-- 查询本季度数据
select * from `ht_invoice_information` where QUARTER(create_date)=QUARTER(now());
-- 查询上季度数据
select * from `ht_invoice_information` where QUARTER(create_date)=QUARTER(DATE_SUB(now(),interval 1 QUARTER));
-- 查询本年数据
select * from `ht_invoice_information` where YEAR(create_date)=YEAR(NOW());
-- 查询上年数据
select * from `ht_invoice_information` where year(create_date)=year(date_sub(now(),interval 1 year));
-- 查询当前这周的数据
SELECT name, submittime FROM enterprise WHERE YEARWEEK(date_format(submittime,'%Y-%m-%d')) = YEARWEEK(now());
-- 查询上周的数据
SELECT name, submittime FROM enterprise WHERE YEARWEEK(date_format(submittime,'%Y-%m-%d')) = YEARWEEK(now())-1;
-- 查询当前月份的数据
select name, submittime from enterprise where date_format(submittime,'%Y-%m')=date_format(now(),'%Y-%m')
-- 查询距离当前现在6个月的数据
select name, submittime from enterprise where submittime between date_sub(now(),interval 6 month) and now();
-- 查询上个月的数据
select name, submittime from enterprise where date_format(submittime,'%Y-%m')=date_format(DATE_SUB(curdate(), INTERVAL 1 MONTH),'%Y-%m')

Links

  • 2022-Next Level Database Techniques For Developers
上一页