数据库篇-关系型数据库-MySql-MySql的高级应用-存储过程、游标、触发器、分区、EXPLAIN等

存储过程

关键字

DELIMITER //  
  
CREATE PROCEDURE CalculateSquare(IN num INT, OUT result INT)  
BEGIN  
    SET result = num * num;  
END //  
  
DELIMITER ;

存储过程的 while ···· end while

DELIMITER //  

create procedure proc4()  
begin 
declare var int;

set
var = 0;

while var<6 do  
insert
	into
	t
values(var);

set
var = var + 1;
end while;
end;

//  
DELIMITER ;

查看存储过程

show procedure status where db='test01';

删除存储过程

drop PROCEDURE createPartition;

创建存储过程

DELIMITER $$

CREATE PROCEDURE createPartition(IN in_TABLE_SCHEMA VARCHAR(255),IN in_tableName VARCHAR(255),IN in_cjrq VARCHAR(8))
BEGIN
    DECLARE pname VARCHAR(255) DEFAULT "";
    DECLARE exists_flag int DEFAULT 0;

    -- 要执行的 sql语句
    DECLARE sql_stmt VARCHAR(1000);
    set pname = CONCAT('p',substring(in_cjrq,1,6) );
   
    select count(1)  into exists_flag FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA = in_TABLE_SCHEMA AND table_name = in_tableName AND PARTITION_NAME = pname ;
   	-- 如果是0 表示 不存在对应分区,创建分区
    IF exists_flag = 0 then
        SET @sql_stmt = CONCAT('ALTER TABLE ', in_tableName,' ADD PARTITION (PARTITION ', pname, ' VALUES IN (', QUOTE(in_cjrq), '))');
        PREPARE stmt FROM @sql_stmt;
        EXECUTE stmt;
        DEALLOCATE PREPARE stmt;
    END IF;
end

$$
DELIMITER ;

存储过程中创建分区

-- 创建新分区  
-- 这行是一个注释,说明接下来的代码块将用于创建一个新的表分区  
  
SET @sql = CONCAT('ALTER TABLE sales ADD PARTITION (PARTITION ', new_partition_name,     
                  ' VALUES LESS THAN (TO_DAYS(''', DATE_FORMAT(new_partition_value, '%Y-%m-01'), ''')))');  
-- 这行代码执行了几个操作:  
-- 1. 使用CONCAT函数构建一个动态的SQL语句字符串。这个字符串是一个ALTER TABLE语句,用于向sales表中添加一个新的分区。  
-- 2. ALTER TABLE sales ADD PARTITION ... 是MySQL中用于向已存在的表添加新分区的SQL语法。  
-- 3. PARTITION 关键字后面跟着的是新分区的名称,由变量new_partition_name提供。  
-- 4. VALUES LESS THAN (TO_DAYS('...')) 指定了分区值的范围。这里使用了TO_DAYS函数将日期转换为天数,以便与分区键(在这个例子中是sale_date)进行比较。  
-- 5. DATE_FORMAT(new_partition_value, '%Y-%m-01') 将变量new_partition_value(代表新分区的起始日期)格式化为'YYYY-MM-01'的形式,即该月的第一天。这是为了确保分区包含整个月的数据。  
-- 6. CONCAT函数将所有这些部分组合成一个完整的SQL语句字符串,存储在变量@sql中。  
  
PREPARE stmt FROM @sql;  
-- 这行代码准备了一个SQL语句执行对象stmt,用于执行存储在变量@sql中的SQL语句。PREPARE语句是MySQL中用于动态执行SQL语句的一种方式。  
  
EXECUTE stmt;  
-- 这行代码执行了之前通过PREPARE语句准备好的SQL语句。在这个例子中,它执行了ALTER TABLE语句,向sales表中添加了一个新的分区。  
  
DEALLOCATE PREPARE stmt;  
-- 最后,这行代码释放了之前通过PREPARE语句分配的资源。在MySQL中,使用PREPARE语句创建的SQL语句执行对象需要在使用完毕后被释放,以避免资源泄露。

调用存储过程

-- 测试存储过程
call createPartition('test01','bp_dczc_tmp','20240831')

触发器

before|after insert|update|delete

insert 中 new.id

delete中的 old.id

update 中的new.id及old.id

创建插入触发器

create trigger insert_bp_dczc_tmp before insert 
	on bp_dczc_tmp for each row
	begin
		DECLARE tname VARCHAR(255) DEFAULT 'bp_dczc_tmp';
		DECLARE pcjrq date;
		set pcjrq = new.cjrq;
		-- 调用存储过程,判断是否需要创建表分区
		call createPartition(tname,pcjrq);
	end

查看触发器

SHOW TRIGGERS ;

删除触发器

DROP TRIGGER insert_bp_dczc_tmp; 

分区

MySQL分区是将一张表分割成独立的子表的技术。

​ 每个子表被称为分区,它们有着相同的结构和字段,但存储着不同的数据。这项技术可以提高查询速度,减少日志文件和磁盘空间的使 用。

分区字段:

​ 必须定义一个或多个分区字段来确定如何将数据行分配到各个分区中。分区字段必须是表的主键或唯一索引之一。

分区类型:

​ MySQL提供了多种分区类型,包括范围分区、哈希分区和列表分区。

LIST分区

LIST分区是根据某一列的离散值将数据分布到不同的分区。每个分区包含特定的列值列表。

  1. 指定分区键:选择作为分区依据的列作为分区键,通常是具有离散值的列,如地区、类别等。
  2. 分区函数:通过PARTITION BY LIST指定使用LIST分区策略。
  3. 定义分区列表:使用VALUES IN子句定义每个分区包含的列值列表。
CREATE TABLE users (
id INT,
username VARCHAR(50),
region VARCHAR(50)
)
PARTITION BY LIST (region) (
PARTITION p_east VALUES IN ('New York', 'Boston'),
PARTITION p_west VALUES IN ('Los Angeles', 'San Francisco'),
PARTITION p_other VALUES IN (DEFAULT)
);
CREATE TABLE employees (
  employee_id int(6) primary key,
  first_name varchar(20),
  last_name varchar(25),
  email varchar(25),
  phone_number varchar(20),
  hire_date datetime, 
  job_id varchar(10),
  salary int(8),
  commission_pct decimal(2,2),
  manager_id decimal(6,0),
  department_id int(4)
)
PARTITION BY LIST(employee_id) (
    PARTITION p0 VALUES IN (101,103,105,107,109),
    PARTITION p1 VALUES IN (102,104,106,108,110)
);

INSERT INTO employees VALUES ('100', 'Steven', 'King', 'SKING', '515.123.4567', '1987-06-17 00:00:00', 'AD_PRES', '24000.00', null, null, '90');

RANGE分区

RANGE分区是MySQL中的一种分区策略,根据某一列的范围值将数据分布到不同的分区。每个分区包含特定的范围。

定义方式:

  1. 指定分区键:选择作为分区依据的列作为分区键,通常是日期、数值等具有范围特性的列。
  2. 分区函数:通过PARTITION BY RANGE指定使用RANGE分区策略。
  3. 定义分区范围:使用VALUES LESS THAN子句定义每个分区的范围。
CREATE TABLE sales (
    id INT,
    sales_date DATE,
    amount DECIMAL(10, 2)
)
PARTITION BY RANGE (YEAR(sales_date)) (
    PARTITION p1 VALUES LESS THAN (2020),
    PARTITION p2 VALUES LESS THAN (2021),
    PARTITION p3 VALUES LESS THAN (2022),
    PARTITION p4 VALUES LESS THAN MAXVALUE
);

HASH分区

  • HASH分区是使用哈希算法将数据均匀地分布到多个分区中。
  1. 指定分区键:选择作为分区依据的列作为分区键。
  2. 分区函数:通过PARTITION BY HASH指定使用HASH分区策略。
  3. 定义分区数量:使用PARTITIONS关键字指定分区的数量。

特点

数据均匀分布:HASH分区使用哈希算法将数据均匀地分布到不同的分区中,确保数据在各个分区之间平衡。
并行查询性能:通过将数据分散到多个分区,HASH分区可以提高并行查询的性能,多个查询可以同时在不同分区上执行。
简化管理:HASH分区使得数据管理更加灵活,可以轻松地添加或删除分区,以适应数据增长或变更的需求。

CREATE TABLE sensor_data (
id INT,
sensor_name VARCHAR(50),
value INT
)
PARTITION BY HASH (id)
PARTITIONS 4;

PARTITION BY HASH (id):指定使用HASH分区,基于id列的哈希值进行分区。
PARTITIONS 4:指定创建4个分区。

COLUMNS 分区

RANGE COLUMNS分区和LIST COLUMNS分区

RANGE COLUMNS分区

RANGE COLUMNS分区: RANGE COLUMNS分区是根据列的范围值将数据分布到不同的分区的分区策略。它类似于RANGE分区,但是根据多个列的范围值进行分区,而不是只根据一个列。这使得范围的定义更加灵活,可以基于多个列的组合来进行分区。

CREATE TABLE sales (
   id INT,
   sales_date DATE,
   region VARCHAR(50),
   amount DECIMAL(10,2)
   )
   PARTITION BY RANGE COLUMNS(region, sales_date) (
   PARTITION p1 VALUES LESS THAN ('East', '2022-01-01'),
   PARTITION p2 VALUES LESS THAN ('West', '2022-01-01'),
   PARTITION p3 VALUES LESS THAN ('East', MAXVALUE),
   PARTITION p4 VALUES LESS THAN ('West', MAXVALUE)
   );

创建了一个名为sales的表,并使用RANGE COLUMNS分区策略。根据region和sales_date两列的范围将数据分布到不同的分区。每个分区根据这两列的范围值进行划分。
创建 list COLUMNS 分区表

LIST COLUMNS分区: LIST COLUMNS分区是根据列的离散值将数据分布到不同的分区的分区策略。它类似于LIST分区,但是根据多个列的离散值进行分区,而不是只根据一个列。这使得离散值的定义更加灵活,可以基于多个列的组合来进行分区。

CREATE TABLE users (
   id INT,
   username VARCHAR(50),
   region VARCHAR(50),
   category VARCHAR(50)
   )
   PARTITION BY LIST COLUMNS(region, category) (
   PARTITION p_east VALUES IN (('New York', 'A'), ('Boston', 'B')),
   PARTITION p_west VALUES IN (('Los Angeles', 'C'), ('San Francisco', 'D')),
   PARTITION p_other VALUES IN (DEFAULT)
   );
-- 创建 list COLUMNS 分区表
CREATE TABLE `bp_dczc_tmp` (
  `XTXMBH` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '信托项目编号',
  `cjrq` date DEFAULT NULL COMMENT '采集日期'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci

PARTITION BY LIST  COLUMNS(cjrq)
(PARTITION p202404 VALUES IN ('2024-04-30') ENGINE = InnoDB,
 PARTITION p202405 VALUES IN ('2024-05-31') ENGINE = InnoDB,
 PARTITION p202406 VALUES IN ('2024-06-30') ENGINE = InnoDB) 

LIST COLUMNS分区表,分区字段支持使用CHAR VARCHAR DATE等数据类型。普通的LIST分区表分区字段必须是INT类型。

添加分区

使用alter tableadd/drop partition新增/删除分区:

ALTER TABLE employees ADD PARTITION(PARTITION p2 VALUES IN (111,112,113,114,115));
ALTER TABLE sales ADD PARTITION (
    PARTITION p5 VALUES LESS THAN (2023)
);


ALTER TABLE employees DROP PARTITION p2;

删除分区

 alter table bp_dczc_tmp drop partition p202407; 

-- 仅仅删除数据
alter table bm_scenes_data_reminder truncate partition p20210104; 

重新组织分区

CREATE TABLE sales (
    id INT,
    sales_date DATE,
    amount DECIMAL(10,2)
)
PARTITION BY RANGE (YEAR(sales_date)) (
    PARTITION p1 VALUES LESS THAN (2020),
    PARTITION p2 VALUES LESS THAN (2021),
    PARTITION p3 VALUES LESS THAN (2022),
    PARTITION p4 VALUES LESS THAN MAXVALUE
);


ALTER TABLE sales REORGANIZE PARTITION p1, p2, p5 INTO (
    PARTITION p1 VALUES LESS THAN (2020),
    PARTITION p2 VALUES LESS THAN (2022),
    PARTITION p3 VALUES LESS THAN MAXVALUE
);

合并相邻的分区:

ALTER TABLE sales COALESCE PARTITION p1, p2;

分析指定分区的统计信息

ALTER TABLE sales ANALYZE PARTITION p1;

通过 information_schema.PARTITIONS 查看 表分区信息

SELECT  PARTITION_NAME FROM information_schema.PARTITIONS 
WHERE TABLE_SCHEMA="test01" AND table_name='bp_dczc_tmp'	

判断分区是否存在

SELECT  count(1) PARTITION_NAME FROM information_schema.PARTITIONS 
WHERE TABLE_SCHEMA="test01" AND table_name='bp_dczc_tmp' and PARTITION_NAME = 'p202407';

EXPLAIN

EXPLAIN 命令是一个非常有用的工具,可以帮助你了解 MySQL 如何执行查询,并找到优化查询性能的方法。

在 MySQL 中,可以使用 EXPLAIN 命令来查看 SQL 语句的执行计划。执行计划提供了关于 MySQL 如何执行查询的信息,包括使用的索引、连接方式、扫描的行数等。

例如:
EXPLAIN SELECT column1, column2,... FROM table_name WHERE condition;
EXPLAIN SELECT * FROM employees WHERE salary > 5000;

二、解释执行计划的结果

执行 EXPLAIN 命令后,会返回以下列信息:

  1. id:查询的标识符。如果有多个查询(如子查询或连接查询),每个查询都有一个唯一的 id
  2. select_type:查询的类型,例如 SIMPLE(简单查询,没有子查询或连接)、PRIMARY(主查询)、SUBQUERY(子查询)等。
  3. table:查询涉及的表名。
  4. partitions:如果表使用了分区,这里会显示分区信息。
  5. type:连接类型,表示 MySQL 如何访问表中的行。常见的类型有 ALL(全表扫描)、index(索引全扫描)、range(索引范围扫描)、ref(使用非唯一索引进行查找)、eq_ref(使用唯一索引进行查找)等。连接类型的性能从差到好依次为:ALL < index < range < ref < eq_ref
  6. possible_keys:可能使用的索引。
  7. key:实际使用的索引。如果没有使用索引,这里为 NULL
  8. key_len:索引中使用的字节数。可以帮助确定索引的使用情况。
  9. ref:表示索引列与常量或其他列的比较。
  10. rows:估计需要扫描的行数。
  11. filtered:表示满足条件的行数的百分比估计。
  12. Extra:额外的信息,例如 Using index(仅使用索引进行查询)、Using where(使用了 WHERE 子句进行过滤)、Using temporary(使用了临时表)等。

三、优化查询

通过分析 EXPLAIN 的结果,可以采取以下措施来优化查询:

  1. 添加合适的索引:如果查询使用了全表扫描或性能较差的连接类型,可以考虑在查询中涉及的列上添加索引。

  2. 优化查询条件:确保 WHERE 子句中的条件能够有效地使用索引。避免使用函数或表达式对索引列进行操作,因为这可能会导致索引无法使用。

  3. 优化连接顺序:对于连接查询,调整连接顺序可能会提高性能。可以通过分析 EXPLAIN 结果中的 rowstype 列来确定最佳的连接顺序。

    1. 优化查询条件

      1. 确保查询条件中的列与索引匹配。如果在索引列上使用函数或表达式,可能会导致索引无法使用。
        • 例如,不要使用 WHERE column_name + 1 = 10,而应该使用 WHERE column_name = 9
      2. 避免使用不明确的条件,如 LIKE '%value%',这种条件通常会导致全表扫描。如果可能,尽量使用明确的起始字符进行模糊查询,如 LIKE 'value%'

      三、调整连接顺序

      1. 在多表连接查询中,连接顺序可能会影响连接类型和性能。
      2. 尝试不同的连接顺序,观察 EXPLAIN 输出的连接类型和扫描行数的变化。一般来说,先连接较小的表或选择性较高的表可能会提高性能。
  4. 避免使用临时表:如果 Extra 列中显示 Using temporary,说明查询使用了临时表,这可能会降低性能。可以尝试优化查询以避免使用临时表。

方法

数值

ABS

求绝对值

SQRT

求二次方根

MOD

求余数

CEIL 和 CEILING

两个函数功能相同,都是返回不小于参数的最小整数,即向上取整

FLOOR

向下取整,返回值转化为一个BIGINT

RAND

生成一个0~1之间的随机数,传入整数参数是,用来产生重复序列

ROUND

对所传参数进行四舍五入

SIGN

返回参数的符号

字符串

LENGTH

计算字符串长度函数,返回字符串的字符长度

在 MySQL 中,LENGTH()函数用于返回字符串的字符长度。它计算的是字符串中字符的个数,而不是字节数。

LENGTH(str),其中str是要计算长度的字符串

使用LENGTH()函数来确保字符个数符合要求,

LENGTHB()

lengthb()函数用于返回字符串的字节长度。字节长度的计算依据是字符串所采用的字符编码。这与length()函数不同,length()返回的是字符个数,而lengthb()关注的是字节层面的长度。

  • UTF - 8 编码:UTF - 8 是一种广泛使用的可变长字符编码。在 UTF - 8 编码下,ASCII 字符(如英文字母、数字和常见标点符号)占用 1 个字节。然而,对于非 ASCII 字符,如汉字,通常占用 3 个字节。

LENGTHB(str)`

INSERT

替换字符串函数

LOWER/UPPER

将字符串中的字母转换为 小写/大写

LEFT

从左侧字截取符串,返回字符串左边的若干个字符

RIGHT

从右侧字截取符串,返回字符串右边的若干个字符

TRIM

删除字符串左右两侧的空格

REPLACE

字符串替换函数,返回替换后的新字符串

SUBSTRING

截取字符串,返回从指定位置开始的指定长度的字符换

REVERSE

字符串反转(逆序)函数,返回与原始字符串顺序相反的字符串

CONCAT( s1,s2…sn)

合并多个字符串,需要注意,返回结果为连接参数产生的字符串。如有任何一个参数为NULL ,则返回值为 NULL 合并多个字符串,

SELECT CONCAT(“SQL”, “Tutorial”, “is”, “fun!”)AS ConcatenatedString;

CONCAT_WS(x, s1,s2…sn)

同 CONCAT(s1,s2,…) 函数,但是每个字符串之间要加上 x,x 可以是分隔符,需要注意的是分隔符不能为null,如果为null,则返回结果为null 合并多个字符串,并添加分隔符

SELECT CONCAT_WS(“-”, “SQL”, “Tutorial”, “is”, “fun!”)AS ConcatenatedString;

FIELD(s,s1,s2…)

返回第一个字符串 s 在字符串列表(s1,s2…)中的位置:从1开始 返回字符串 c 在列表值中的位置:SELECT FIELD(“c”, “a”, “b”, “c”, “d”, “e”);
ELT(N,str1,str2,str3,…) 返回对应位置的字符串。如果N = 1,则返回str1;如果N = 2,则返回str2,依此类推。 如果N小于1或大于参数个数,则返回NULL。 ELT是FIELD的补充。

SELECT ELT(1, ‘ej’, ‘Heja’, ‘hej’, ‘foo’);

FIND_IN_SET(s1,s2)

返回在字符串s2中与s1匹配的字符串的位置:从1开始 返回字符串 c 在指定字符串中的位置:SELECT FIND_IN_SET(“c”, “a,b,c,d,e”);

FORMAT(x,n)

函数可以将数字 x 进行格式化 “#,###.##”, 将 x 保留到小数点后 n 位,最后一位四舍五入。 格式化数字 “#,###.##” 形式:

SELECT FORMAT(250500.5634, 2); – 输出 250,500.56

INSERT(s1,x,len,s2)

字符串 s2 替换 s1 的 x 位置开始长度为 len 的字符串

从字符串第一个位置开始的 6 个字符替换为 runoob:

SELECT INSERT(“google.com”, 1, 6, “runoob”); – 输出:runoob.com

LOCATE(s1,s)

从字符串 s 中获取 s1 的开始位置 获取 b 在字符串 abc 中的位置:

SELECT LOCATE(‘st’,‘myteststring’); – 5
SELECT LOCATE(‘st’,‘myteststring’)>0 ; 根据> 0 判断字符串 s 是否包含 子字符串 s1

LOWER(s)

将字符串 s 的所有字母变成小写字母 字符串 RUNOOB 转换为小写SELECT LOWER(‘RUNOOB’) – runoob

UPPER(s)

将字符串转换为大写 将字符串 runoob 转换为大写:SELECT UPPER(“runoob”); – RUNOOB

LEFT(s,n)

返回字符串 s 的前 n 个字符 返回字符串 runoob 中的前两个字符:SELECT LEFT(‘runoob’,2) – ru

RIGHT(s,n)

返回字符串 s 的后 n 个字符 返回字符串 runoob 的后两个字符:SELECT RIGHT(‘runoob’,2) – ob

LPAD(s1,len,s2)

在字符串 s1 的开始处填充字符串 s2,使字符串长度达到 len 将字符串 xx 填充到 abc 字符串的开始处:SELECT LPAD(‘abc’,5,‘xx’) – xxabc

RPAD(s1,len,s2)

在字符串 s1 的结尾处添加字符串 s2,使字符串的长度达到 len 将字符串 xx 填充到 abc 字符串的结尾处:SELECT RPAD(‘abc’,5,‘xx’) – abcxx

TRIM(s)

去掉字符串 s 开始和结尾处的空格 去掉字符串 RUNOOB 的首尾空格:SELECT TRIM(’ RUNOOB ') AS TrimmedString;

LTRIM(s)

去掉字符串 s 左侧的空格 去掉字符串 RUNOOB开始处的空格:SELECT LTRIM(" RUNOOB") AS LeftTrimmedString;-- RUNOOB

RTRIM(s)

去掉字符串 s 结尾处的空格 去掉字符串 RUNOOB 的末尾空格:·SELECT RTRIM("RUNOOB ") AS RightTrimmedString; – RUNOOB·

REPLACE(s,s1,s2)

将字符串 s2 替代字符串 s 中的字符串 s1;将字符串 abc 中的字符 a 替换为字符 x:SELECT REPLACE('abc','a','x') --xbc

SUBSTR(s, start, length)

从字符串 s 的 start 位置截取长度为 length 的子字符串 从字符串 RUNOOB 中的第 2 个位置截取 3个 字符 SELECT SUBSTR(“RUNOOB”, 2, 3) AS ExtractString; – UNO

SUBSTRING(s, start, length)

从字符串 s 的 start 位置截取长度为 length 的子字符串 从字符串 RUNOOB 中的第 2 个位置截取 3个 字符:SELECT SUBSTRING(“RUNOOB”, 2, 3) AS ExtractString; – UNO

SUBSTRING_INDEX(s, delimiter, number)

string:用于截取目标字符串的字符串。可为字段,表达式等。

sep:分隔符,string存在且用于分割的字符,比如“,”、“.”等。

num:序号,为非0整数。若为整数则表示从左到右数,若为负数则从右到左数。比如“www.mysql.com”截取字符‘www’,分割符为“.”,从左到右序号为1,即substring_index(“www.mysql.com”,‘.’,1);若从右开始获取“com”则为序号为-1即

返回从字符串 s 的第 number 个出现的分隔符 delimiter 之后的子串。如果 number 是正数,返回第 number 个字符左边的字符串。如果 number 是负数,返回第(number 的绝对值(从右边数))个字符右边的字符串。

SELECT SUBSTRING_INDEX(‘ab’,'’,1) – a

SELECT SUBSTRING_INDEX(‘ab’,'’,-1) – b

SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(‘abcde’,‘‘,3),’’,-1) – c

GREATEST(expr1, expr2, expr3, …)

返回列表中的最大值 返回以下数字列表中的最大值:SELECT GREATEST(3, 12, 34, 8, 25); – 34返回以下字符串列表中的最大值:SELECT GREATEST(“Google”, “Runoob”, “Apple”); – Runoob

ROUND(x,y)

返回离 y位数 最近的整数(四舍五入) SELECT ROUND(1.23456) --1

TRUNCATE(x,y)

返回数值 x 保留到小数点后 y 位的值(与 ROUND 最大的区别是不会进行四舍五入) SELECT TRUNCATE(1.23456,3) – 1.234

日期

CURDATE 和 CURRENT_DATE

两个函数作用相同,返回当前系统的日期值

CURTIME 和 CURRENT_TIME

两个函数作用相同,返回当前系统的时间值

NOW 和 SYSDATE

两个函数作用相同,返回当前系统的日期和时间值

UNIX_TIMESTAMP

获取UNIX时间戳函数,返回一个以 UNIX 时间戳为基础的无符号整数

FROM_UNIXTIME

将 UNIX 时间戳转换为时间格式,与UNIX_TIMESTAMP互为反函数

MONTH

获取指定日期中的月份

MONTHNAME

获取指定日期中的月份英文名称

DAYNAME

获取指定曰期对应的星期几的英文名称

DAYOFWEEK

获取指定日期对应的一周的索引位置值

WEEK

获取指定日期是一年中的第几周,返回值的范围是否为 0〜52 或 1〜53

ADDDATE(d,n) 计算起始日期 d 加上 n 天的日期 SELECT ADDDATE("2017-06-15", INTERVAL 10 DAY); ->2017-06-25
ADDTIME(t,n) n 是一个时间表达式,时间 t 加上时间表达式 n 加 5 秒:SELECT ADDTIME('2011-11-11 11:11:11', 5); ->2011-11-11 11:11:16 (秒)添加 2 小时, 10 分钟, 5 秒:SELECT ADDTIME("2020-06-15 09:34:21", "2:10:5"); -> 2020-06-15 11:44:26
CURDATE() 返回当前日期 SELECT CURDATE(); -> 2018-09-19
CURRENT_DATE() 返回当前日期 SELECT CURRENT_DATE(); -> 2018-09-19
CURRENT_TIME 返回当前时间 SELECT CURRENT_TIME(); -> 19:59:02
CURRENT_TIMESTAMP() 返回当前日期和时间 SELECT CURRENT_TIMESTAMP() -> 2018-09-19 20:57:43
CURTIME() 返回当前时间 SELECT CURTIME(); -> 19:59:02
DATE() 从日期或日期时间表达式中提取日期值 SELECT DATE("2017-06-15"); -> 2017-06-15
DATEDIFF(d1,d2) 计算日期 d1->d2 之间相隔的天数 SELECT DATEDIFF('2001-01-01','2001-02-02') -> -32
DATE_ADD(d,INTERVAL expr type) 计算起始日期 d 加上一个时间段后的日期,type 值可以是:MICROSECONDSECONDMINUTEHOURDAYWEEKMONTHQUARTERYEARSECOND_MICROSECONDMINUTE_MICROSECONDMINUTE_SECONDHOUR_MICROSECONDHOUR_SECONDHOUR_MINUTEDAY_MICROSECONDDAY_SECONDDAY_MINUTEDAY_HOURYEAR_MONTH SELECT DATE_ADD("2017-06-15", INTERVAL 10 DAY); -> 2017-06-25 SELECT DATE_ADD("2017-06-15 09:34:21", INTERVAL 15 MINUTE); -> 2017-06-15 09:49:21 SELECT DATE_ADD("2017-06-15 09:34:21", INTERVAL -3 HOUR); ->2017-06-15 06:34:21 SELECT DATE_ADD("2017-06-15 09:34:21", INTERVAL -3 MONTH); ->2017-03-15 09:34:21
DATE_FORMAT(d,f) 按表达式 f的要求显示日期 d SELECT DATE_FORMAT('2011-11-11 11:11:11','%Y-%m-%d %r') -> 2011-11-11 11:11:11 AM
DATE_SUB(date,INTERVAL expr type) 函数从日期减去指定的时间间隔。 Orders 表中 OrderDate 字段减去 2 天:SELECT OrderId,DATE_SUB(OrderDate,INTERVAL 2 DAY) AS OrderPayDate FROM Orders
DAY(d) 返回日期值 d 的日期部分 SELECT DAY("2017-06-15"); -> 15
LAST_DAY(d) 返回给给定日期的那一月份的最后一天 SELECT LAST_DAY("2017-06-20"); -> 2017-06-30
SUBDATE(d,n) 日期 d 减去 n 天后的日期 SELECT SUBDATE('2011-11-11 11:11:11', 1) ->2011-11-10 11:11:11 (默认是天)
CAST(x AS type)

转换数据类型 字符串日期转换为日期:SELECT CAST(“2017-08-29” AS DATE);-> 2017-08-29 字符串转换为数字SELECT CAST(“2” AS signed);

COALESCE(expr1, expr2, …, expr_n)

返回参数中的第一个非空表达式(从左向右) SELECT COALESCE(NULL, NULL, NULL, ‘runoob.com’, NULL, ‘google.com’);-> runoob.com

其它高级

select GROUP_CONCAT(DISTINCT data_code order by data_code desc separator '_') from sip_dic_info c where c.data_type = 'BC_02';
group_concat()

1、功能:将group by产生的同一个分组中的值连接起来,返回一个字符串结果。
2、语法:group_concat( [distinct] 要连接的字段 [order by 排序字段 asc/desc ] [separator ‘分隔符’] )
说明:通过使用distinct可以排除重复值;如果希望对结果中的值进行排序,可以使用order by子句;separator是一个字符串值,缺省为一个逗号。

MySql数据库查询时,使用group_concat报错“Row XXX was cut by GROUP_CONCAT()”,单独查询不会报错,当我要查询的数据更新到另外个表中的字段时,会报这个错,网上查了下是因为GROUP_CONCAT有个最大长度的限制,超过最大长度就会被截断掉,可以通过

show variables like "group_concat_max_len";
-- SET GLOBAL group_concat_max_len=102400;
 
-- SET group_concat_max_len=102400;
类型转换cast 或者convert
SELECT CAST("2017-08-29" AS DATE);
SELECT CAST("2" AS signed); 
select CONVERT('12332',signed); // 有多个重载函数

binary:二进制类型;
char:字符类型;
date:日期类型;
time:时间类型;
datetime:日期时间类型;
decimal:浮点型;
signed:整型;
unsigned:无符号整型。

基础

LENGTH

计算字符串长度函数,返回字符串的字符长度

这个可以用来配合varchar()

LENGTHB()

lengthb()函数用于返回字符串的字节长度。

这个可以用来配合varchar2()

varchar是标准sql(mysql)里面的。 varchar2是oracle提供的独有的数据类型。

==varchar对于汉字占两个字节,对于数字,英文字符是一个字节,占的内存小,varchar2一般情况下把所有字符都占两字节处理。==具体要看数据库使用的字符集,比如GBK,汉字就会占两个字节,英文1个,如果是UTF-8,汉字一般占3个字节,英文还是1个。

varchar对空串不处理,varchar2将空串当做null来处理。

varchar存放可变长,最大2000,varchar2是存放可变长度的字符串,最大长度是4000.

如果是要更换不同的数据库,例如mysql,那么就用varchar,如果就用oracle,那么用varchar2比较好一点。

你可能感兴趣的:(1024程序员节)