type | Storage | Minumun Value | Maximum Value |
---|---|---|---|
(Bytes) | (Signed/Unsigned) | (Signed/Unsigned) | |
TINYINT | 1 | -128 | 127 |
0 | 255 | ||
SMALLINT | 2 | -32768 | 32767 |
0 | 65535 | ||
MEDIUMINT | 3 | -8388608 | 8388607 |
0 | 16777215 | ||
INT | 4 | -2147483648 | 2147483647 |
0 | 4294967295 | ||
BIGINT | 8 | -9223372036854775808 | 9223372036854775807 |
0 | 18446744073709551615 |
int(11) VS int(21)
存储空间,还是存储范围有区别?
答案是:两者完全一样,只是在显示的时候补全0的位数不一样。
可以通过下面的例子来验证:
create table t(a int(11) zerofill, b int(21) zerofill);
insert into t values (1, 1);
select * from t;
MySQL默认是不带0补全的。
只是在一些特殊情况下两者显示有区别,其本质完全一样。
属性 | 存储空间 | 精度 | 精确性 |
---|---|---|---|
Float | 4 bytes | 单精度 | 非精确 |
Double | 8 bytes | 双精度 | 比Float精度高 |
一个例子:
create table t(a int(11), b float(7, 4));
insert into t values (2, 123.12345);
select * from t;
一般使用tinyint、char(1)、enum类型。
编码\输入字符串 | 网易 | netease |
---|---|---|
gbk(双字节) | varchar(2)/4 bytes | varchar(7)/7 bytes |
utf8(三字节) | varchar(2)/6 bytes | varchar(7)/7 bytes |
utf8mb4(四字节) | varchar(2) ? | varchar(7)/7 bytes |
对于utf8mb4号称占用四字节但是并不绝对。如果在utf8可以覆盖到的范围则仍然占用3字节。
utf8mb4最有优势的应用场景是用于存储emoji表情
一个例子:
create table t (a char(256));
create table t (a varchar(256));
性能太差,不推荐
存储空间上的区别
存储精度的区别
MySQL在5.6.4版本之后,TimeStamp和DateTime支持到微妙
一个例子:
create table test (a datetime, b timestamp);
select now();
insert into test values (now(), now());
select * from test;
set time_zone = '+00:00';
select * from test;
CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name
[index_type]
ON tbl_name (index_col_name,...)
[index_option]
[algorithm_option | lock_option] ...
index_col_name:
col_name [(length)] [ASC | DESC]
index_type:
USING {BTREE | HASH}
ALTER [IGNORE] TABLE tbl_name
[alter_specification [, alter_specification] ...]
[partition_options]
alter_specification:
table_options
| ADD [COLUMN] col_name column_definition
[FIRST | AFTER col_name]
ADD [COLUMN] (col_name column_definition,...)
ADD {INDEX|KEY} [index_name]
[index_type] (index_col_name,...) [index_option] ...
| ADD [CONSTRAINT [symbol]] PRIMARY KEY
[index_type] (index_col_name,...) [index_option] ...
| ADD [CONSTRAINT [symbol]]
UNIQUE [INDEX|KEY] [index_name]
以如下这张表为例
CREATE TABLE `order` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`orderid` int(10) unsigned NOT NULL,
`bookid` int(10) unsigned NOT NULL DEFAULT '0',
`userid` int(10) unsigned NOT NULL DEFAULT '0',
`number` tinyint(3) unsigned NOT NULL DEFAULT '0',
`address` varchar(128) NOT NULL DEFAULT '',
`postcode` varchar(128) NOT NULL DEFAULT '',
`orderdate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`status` tinyint(3) unsigned zerofill DEFAULT '000',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_orderid` (`orderid`),
UNIQUE KEY `idx_uid_orderid` (`userid`, `orderid`),
KEY `bookid` (`bookid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
show privileges
命令可以查看全部权限
GRANT
priv_type [(column_list)]
[, priv_type [column_list]] ...
ON [object_type] priv_level
TO user_specification [, user_specification] ...
[REQUIRE {NONE | ssl_option [[AND] ssl_option] ...}]
[WITH with_option ...]
GRANT PROXY ON user_specification
TO user_specification [, user_specification] ...
[WITH GRANT OPTION]
CREATE USER 'netease'@'localhost' IDENTIFIED BY 'netease163';
GRANT SELECT ON *.* TO 'netease'@'localhost' WITH GRANT OPTION;
flush privileges
命令,让权限信息生效GRANT SELECT ON *.* TO 'NETEASE'@'localhost' IDENTIFIED BY 'netease163' WITH GRANT OPTION;
show grants;
show grants for netease@'localhost';
revoke select on *.* from netease@'localhost';
grant insert on *.* to netease@'localhost';
DROP USER user [, user] ...
查询时从user->db->table_pirv->columns_pirv依次验证,如果通过则执行查询。
create table tb_account(
account_id int not null auto_increment primary key,
nick_name varchar(20),
true_name varchar(20),
sex char(1),
mail_address varchar(50),
phone1 varchar(20) not null,
phone2 varchar(20),
password varchar(30) not null,
create_time datetime,
account_state tinyint,
last_login_time datetime,
last_login_ip varchar(20)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
create table tb_goods(
good_id bigint not null auto_increment primary key,
goods_name varchar(100) not null,
pic_url varchar(500) not null,
store_quantity int not null,
goods_note varchar(4096),
producer varchar(500),
category_id int not null
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
create table tb_goods_category(
category_id int not null auto_increment primary key,
category_level smallint not null,
category_name varchar(500),
upper_category_id int not null
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
create table tb_order(
order_id bigint not null auto_increment primary key,
account_id int not null,
create_time datetime,
order_amount decimal(12,2),
order_state tinyint,
update_time datetime,
order_ip varchar(20),
pay_method varchar(20),
user_notes varchar(500)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
create table tb_order_item(
order_item_id bigint not null auto_increment primary key,
order_id bigint not null,
goods_id bigint not null,
goods_quantity int not null,
goods_amount decimal(12,2),
uique key uk_order_goods(order_id, goods_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
本课程涉及建表SQL
-- ----------------------------
-- Table structure for `play_fav`
-- ----------------------------
DROP TABLE IF EXISTS `play_fav`;
CREATE TABLE `play_fav` (
`userid` bigint(20) NOT NULL COMMENT '收藏用户id',
`play_id` bigint(20) NOT NULL COMMENT '歌单id',
`createtime` bigint(20) NOT NULL COMMENT '收藏时间',
`status` int(11) DEFAULT '0' COMMENT '状态,是否删除',
PRIMARY KEY (`play_id`,`userid`),
KEY `IDX_USERID` (`userid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='歌单收藏表';
-- ----------------------------
-- Records of play_fav
-- ----------------------------
INSERT INTO play_fav VALUES ('2', '0', '0', '0');
INSERT INTO play_fav VALUES ('116', '1', '1430223383', '0');
INSERT INTO play_fav VALUES ('143', '1', '0', '0');
INSERT INTO play_fav VALUES ('165', '2', '0', '0');
INSERT INTO play_fav VALUES ('170', '3', '0', '0');
INSERT INTO play_fav VALUES ('185', '3', '0', '0');
INSERT INTO play_fav VALUES ('170', '4', '0', '0');
INSERT INTO play_fav VALUES ('170', '5', '0', '0');
-- ----------------------------
-- Table structure for `play_list`
-- ----------------------------
DROP TABLE IF EXISTS `play_list`;
CREATE TABLE `play_list` (
`id` bigint(20) NOT NULL COMMENT '主键',
`play_name` varchar(255) DEFAULT NULL COMMENT '歌单名字',
`userid` bigint(20) NOT NULL COMMENT '歌单作者账号id',
`createtime` bigint(20) DEFAULT '0' COMMENT '歌单创建时间',
`updatetime` bigint(20) DEFAULT '0' COMMENT '歌单更新时间',
`bookedcount` bigint(20) DEFAULT '0' COMMENT '歌单订阅人数',
`trackcount` int(11) DEFAULT '0' COMMENT '歌曲的数量',
`status` int(11) DEFAULT '0' COMMENT '状态,是否删除',
PRIMARY KEY (`id`),
KEY `IDX_CreateTime` (`createtime`),
KEY `IDX_UID_CTIME` (`userid`,`createtime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='歌单';
-- ----------------------------
-- Records of play_list
-- ----------------------------
INSERT INTO play_list VALUES ('1', '老男孩', '1', '1430223383', '1430223383', '5', '6', '0');
INSERT INTO play_list VALUES ('2', '情歌王子', '3', '1430223384', '1430223384', '7', '3', '0');
INSERT INTO play_list VALUES ('3', '每日歌曲推荐', '5', '1430223385', '1430223385', '2', '4', '0');
INSERT INTO play_list VALUES ('4', '山河水', '2', '1430223386', '1430223386', '5', null, '0');
INSERT INTO play_list VALUES ('5', '李荣浩', '1', '1430223387', '1430223387', '1', '10', '0');
INSERT INTO play_list VALUES ('6', '情深深', '5', '1430223388', '1430223389', '0', '0', '1');
-- ----------------------------
-- Table structure for `song_list`
-- ----------------------------
DROP TABLE IF EXISTS `song_list`;
CREATE TABLE `song_list` (
`id` bigint(20) NOT NULL COMMENT '主键',
`song_name` varchar(255) NOT NULL COMMENT '歌曲名',
`artist` varchar(255) NOT NULL COMMENT '艺术节',
`createtime` bigint(20) DEFAULT '0' COMMENT '歌曲创建时间',
`updatetime` bigint(20) DEFAULT '0' COMMENT '歌曲更新时间',
`album` varchar(255) DEFAULT NULL COMMENT '专辑',
`playcount` int(11) DEFAULT '0' COMMENT '点播次数',
`status` int(11) DEFAULT '0' COMMENT '状态,是否删除',
PRIMARY KEY (`id`),
KEY `IDX_artist` (`artist`),
KEY `IDX_album` (`album`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='歌曲列表';
-- ----------------------------
-- Records of song_list
-- ----------------------------
INSERT INTO song_list VALUES ('1', 'Good Lovin\' Gone Bad', 'Bad Company', '0', '0', 'Straight Shooter', '453', '0');
INSERT INTO song_list VALUES ('2', 'Weep No More', 'Bad Company', '0', '0', 'Straight Shooter', '280', '0');
INSERT INTO song_list VALUES ('3', 'Shooting Star', 'Bad Company', '0', '0', 'Straight Shooter', '530', '0');
INSERT INTO song_list VALUES ('4', '大象', '李志', '0', '0', '1701', '560', '0');
INSERT INTO song_list VALUES ('5', '定西', '李志', '0', '0', '1701', '1023', '0');
INSERT INTO song_list VALUES ('6', '红雪莲', '洪启', '0', '0', '红雪莲', '220', '0');
INSERT INTO song_list VALUES ('7', '风柜来的人', '李宗盛', '0', '0', '作品李宗盛', '566', '0');
-- ----------------------------
-- Table structure for `stu`
-- ----------------------------
DROP TABLE IF EXISTS `stu`;
CREATE TABLE `stu` (
`id` int(10) NOT NULL DEFAULT '0',
`name` varchar(20) DEFAULT NULL,
`age` int(10) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
-- ----------------------------
-- Records of stu
-- ----------------------------
-- ----------------------------
-- Table structure for `tbl_proc_test`
-- ----------------------------
DROP TABLE IF EXISTS `tbl_proc_test`;
CREATE TABLE `tbl_proc_test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`num` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=30 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of tbl_proc_test
-- ----------------------------
INSERT INTO tbl_proc_test VALUES ('11', '1');
INSERT INTO tbl_proc_test VALUES ('12', '2');
INSERT INTO tbl_proc_test VALUES ('13', '6');
INSERT INTO tbl_proc_test VALUES ('14', '24');
INSERT INTO tbl_proc_test VALUES ('15', '120');
INSERT INTO tbl_proc_test VALUES ('16', '720');
INSERT INTO tbl_proc_test VALUES ('17', '5040');
INSERT INTO tbl_proc_test VALUES ('18', '40320');
INSERT INTO tbl_proc_test VALUES ('19', '362880');
INSERT INTO tbl_proc_test VALUES ('20', '3628800');
INSERT INTO tbl_proc_test VALUES ('21', '1');
INSERT INTO tbl_proc_test VALUES ('22', '2');
INSERT INTO tbl_proc_test VALUES ('23', '6');
INSERT INTO tbl_proc_test VALUES ('24', '24');
INSERT INTO tbl_proc_test VALUES ('25', '1');
INSERT INTO tbl_proc_test VALUES ('26', '2');
INSERT INTO tbl_proc_test VALUES ('27', '6');
INSERT INTO tbl_proc_test VALUES ('28', '24');
INSERT INTO tbl_proc_test VALUES ('29', '120');
-- ----------------------------
-- Table structure for `tbl_test1`
-- ----------------------------
DROP TABLE IF EXISTS `tbl_test1`;
CREATE TABLE `tbl_test1` (
`user` varchar(255) NOT NULL COMMENT '主键',
`key` varchar(255) NOT NULL,
`value` varchar(255) NOT NULL,
PRIMARY KEY (`user`,`key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='行列转换测试';
-- ----------------------------
-- Records of tbl_test1
-- ----------------------------
INSERT INTO tbl_test1 VALUES ('li', 'age', '18');
INSERT INTO tbl_test1 VALUES ('li', 'dep', '2');
INSERT INTO tbl_test1 VALUES ('li', 'sex', 'male');
INSERT INTO tbl_test1 VALUES ('sun', 'age', '44');
INSERT INTO tbl_test1 VALUES ('sun', 'dep', '3');
INSERT INTO tbl_test1 VALUES ('sun', 'sex', 'female');
INSERT INTO tbl_test1 VALUES ('wang', 'age', '20');
INSERT INTO tbl_test1 VALUES ('wang', 'dep', '3');
INSERT INTO tbl_test1 VALUES ('wang', 'sex', 'male');
-- ----------------------------
-- Procedure structure for `proc_test1`
-- ----------------------------
DROP PROCEDURE IF EXISTS `proc_test1`;
DELIMITER ;;
CREATE DEFINER=`root` PROCEDURE `proc_test1`(IN total INT,OUT res INT)
BEGIN
DECLARE i INT;
SET i = 1;
SET res = 1;
IF total <= 0 THEN
SET total = 1;
END IF;
WHILE i <= total DO
SET res = res * i;
INSERT INTO tbl_proc_test(num) VALUES (res);
SET i = i + 1;
END WHILE;
END
;;
DELIMITER ;
场景1:歌单按时间排序
-- 查看全部歌单
select * from play_list;
-- 按创建时间排序
select * from play_list order by createtime;
-- MySQL默认升序,如果按降序排列,则使用如下语句。
select * from play_list order by createtime desc;
-- 也可以按照多个字段来排序
select * from play_list order by bookedcount, trackcount;
场景2:统计云音乐创建歌单的用户
-- 有重复
select userid from play_list;
-- 去重
select distinct userid from play_list;
-- 多个字段
select distinct userid, play_name from play_list;
场景3-1:统计云音乐创建歌单的用户列表和每人创建歌单的数量。
-- 每个用户歌单的最大订阅数
select userid, max(bookedcount) from play_list group by userid;
-- 每个用户歌单的数量
select userid, count(*) from play_list group by userid;
场景3-2:统计云音乐创建歌单的用户列表和每人创建歌单的数量,并且只显示歌单数量排序大于等于2的用户
select userid, count(*) from play_list group by userid having count(*) >= 2;
SQL进阶语法-like
select * from play_list where play_name like '%男孩%';
通配符 | 描述 |
---|---|
% | 代替一个或多个字符 |
_ | 代替单个字符 |
[charlist] | 中括号中的任何一个字符 |
[^charlist] 或者 [!charlist] | 不在中括号中的任何单一字符 |
* 除了百分号在最右面的情况以外,他会对这个表中所有的记录进行一次查询匹配,而没办法使用索引,效率较低。大表中需要慎用like。可以使用全文检索的手段。
场景4:查询一个月内创建歌单(从第6行开始显示10条记录)
select * from play_list where (createtime between 1427791323 and 1430383307) limit 10 offset 6;
场景5:对于未录入歌曲的歌单(trackcount = null),输出结果时歌曲数返回0.
select case when play_name, trackcount is null then 0 else trackcount end from play_list;
SELECT
[DISTINCT]
select_expr [, select_expr ...]
[FROM table_references
[WHERE where_condition]
[GROUP BY {col_name | expr | position}
[ASC | DESC], ... [WITH ROLLUP]]
[HAVING where_condition]
[ORDER BY {col_name | expr | position}
[ASC | DESC], ...]
[LIMIT { [offset, ] row_count | row_count OFFSET offset}]
[FOR UPDATE | LOCK IN SHARE MODE]]
连接的作用是用一个SQL语句把多个表中相互关联的数据查出来
场景6:查询收藏“老男孩”歌单的用户列表
select * from play_list, play_fav where play_list.id=play_fav.play_id;
select play_fav.userid from play_list, play_fav where play_list.id=play_fav.play_id and play_list.play_name='老男孩';
-- 另一种写法
select f.userid from play_list lst join play_fav f on lst.id=f.play_id where lst.play_name = '老男孩';
select userid from play_fav where play_id=(select id from play_list where play_name = '老男孩');
子查询:内层查询的结果作为外层的比较条件。一般子查询都可以转换成连接,推荐使用连接。
select lst.play_name from play_list lst left join play_fav f on lst.id = f.play_id where f.play_id is null;
场景7:查询出没有用户收藏的歌单
场景8:老板想看创建和收藏歌单的所有用户,查询play_list和play_fav两表中所有的userid
select userid from play_list union select userid from play_fav;
-- 默认会去重, 不想去重的话使用union all代替union。
insert into A values(4, 33), (5, 33);
INSERT INTO TABLE tbl VALUES (id, col1, col2) ON DUPLICATE KEY UPDATE col2=....;
insert into A values(2, 40) on duplicate key update age=40;
update A,B set A.age=B.age where A.id=B.id;
delete A from A,B where A.id=B.id and B.name='pw';
SELECT function(列) from 表
函数 | 描述 |
---|---|
AVG() | 返回列的平均值 |
COUNT(DISTINCT) | 返回列去重后的行数 |
COUNT() | 返回列的行数 |
MAX() | 返回列的最大值 |
MIN() | 返回列的最小值 |
SUM() | 返回列的总和 |
GROUP_CONCAT() | 返回一组值的连接字符串(MySQL独有) |
实例还是上节中的那些表
场景1:查询每张专辑总的点播次数和每首歌的平均点播次数。
select album, sum(playcount), avg(playcount) from song_list group by album;
场景2:查询全部歌曲中的最大的播放次数和最小的播放次数。
select max(playcount), min(playcount) from song_list;
场景2续:查询播放次数最多的歌曲
-- 错误查法
select song_name, max(playcount) from song_list;
-- 正确查法
select song_name, playcount from song_list order by playcount desc limit 1;
select count(*) from song_list;
select count(1) from song_list;
select count(song_name) from song_list;
count(*)
和count(1)
基本一样,没有明显的性能差异。
count(*)
和count(song_name)
差别在于count(song_name)
会除去song_name is null的情况
场景3:显示每张专辑的歌曲列表
select album, GROUP_CONCAT(song_name) from song_list group by album;
-- 默认最大只能连接1024个字符,但是可以通过改数据库参数来改变。
select user,
max(case when 'key'='age' then value end) age,
max(case when 'key'='sex' then value end) sex,
max(case when 'key'='dep' then value end) dep,
from tbl_test1
group by user;
sql
select function(列) from 表;
select * from 表 where 列 = function(value) ...
函数 | 描述 |
---|---|
LENGTH() | 返回列的字节数 |
CHAR_LENGTH() | 返回列的字符数 |
TRIM()/RTRIM()/LTRIM() | 去除两边空格/去除右边空格/去除左边空格 |
SUBSTRING(str, pos, [len]) | 从pos位置截取字符串str,截取len长度 |
LOCATE(substr, str, [pos]) | 返回substr在str字符串中的位置 |
REPLACE(str, from_str, to_str) | 将str字符串中的from_str替换成to_str |
LOWER(), UPPER() | 字符串转换为小写/大写 |
* 字符串函数 - 实例
SELECT SUBSTRING('abcdef', 3);
-- 'cdef'
SELECT SUBSTRING('abcdef', -3);
-- 'def'
SELECT SUBSTRING('abcdef', 3, 2);
-- 'cd'
SELECT LOCATE('bar', 'foobarbar');
-- 4
SELECT LOCATE('xbar', 'foobar');
-- 0
SELECT LOCATE('bar', 'foobarbar', 5);
-- 7
函数 | 描述 |
---|---|
CURDATE() | 当前日期 |
CURTIME() | 当前时间 |
NOW() | 显示当前时间日期(常用) |
UNIX_TIMESTAMP() | 当前时间戳 |
DATE_FORMAT(date, format) | 按指定格式显示时间 |
DATE_ADD(date, INTERVAL unit) | 计算指定日期向后加一段时间的日期 |
DATE_SUB(date, INTERVAL unit) | 计算指定日期向前减一段时间的日期 |
* 实例:
SELECT NOW() + INTERVAL 1 MONTH;
SELECT NOW() - INTERVAL 1 WEEK;
函数 | 描述 |
---|---|
ABS() | 返回数值的绝对值 |
CEIL() | 对小数向上取整 CEIL(1.2)=2 |
ROUND() | 四舍五入 |
POW(num, n) | num的n次幂 POW(2, 2)=4 |
FLOOR() | 对小数向下取整 CELL(1.2)=1 |
MOD(N, M) | 取模(返回n除以m的余数)=N % M |
RAND() | 取0~1之间的一个随机数 |
函数 | 描述 |
---|---|
IS, IS NOT | 判定布尔值 IS True, IS NOT False, IS NULL |
, >= |
大于,大于等于 |
<, <= | 小于,小于等于 |
= | 等于 |
!=, <> | 不等于 |
BETWEEN M AND N | 取M和N之间的值 |
IN, NOT IN | 检查是否在或不在一组值之中 |
实例:查询一个月内userid为1,3,5的用户创建的歌单
select * from play_list where (createtime between 1427791323 and 1430383307) and userid in (1,3,5);
*,/,DIV,%,MOD,-,+
NOT, AND, &&, XOR, OR, ||
CREATE
[DEFINER = { user | CURRENT_USER }]
TRIGGER trigger_name trigger_time
trigger_event ON tbl_name
FOR EACH ROW
trigger_body t
trigger_time: { BEFORE | AFTER }
trigger_event: { INSERT | UPDATE | DELETE }
学生表:
CREATE TABLE `stu` (
`name` varchar(50),
`course` varchar(50),
`score` int(11),
PRIMARY KEY (`name`)
) ENGINE=InnoDB;
用于更正成绩的触发器:
DELIMITER //
CREATE TRIGGER trg_upd_score
BEFORE UPDATE ON `stu`
FOR EACH ROW
BEGIN
IF NEW.score < 0 THEN
SET NEW.score = 0;
ELSEIF NEW.score > 100 THEN
SET NEW.score = 100;
END IF;
END; //
DELIMITER ;
CREATE
[DEFINER = { user | CURRENT_USER }]
PROCEDURE sp_name ([proc_parameter[,...]])
[characteristic ...] routine_body
proc_parameter:
[ IN | OUT | INOUT ] param_name type
type:
Any valid MySQL data type
characteristic:
COMMENT 'string'
| [NOT] DETERMINISTIC
routine_body:
Valid SQL routine statement
CREATE PROCEDURE proc_test1
(IN total INT, OUT res INT)
BEGIN
DECLARE i INT;
SET i = 1;
SET res = 1;
IF total <= 0 THEN
SET total = 1;
END IF;
WHILE i <= total DO
SET res = res * i;
INSERT INTO tbl_proc_test(num) VALUES (res);
SET i = i + 1;
END WHILE;
END;
流控制 | 描述 |
---|---|
IF | IF search_condition THEN statement_list [ELSEIF search_condition THEN statement_list][ELSE statement_list] END IF |
CASE | CASE case_value WHEN when_value THEN statement_list [ELSE statement_list] END CASE |
WHILE | WHILE search_condition DO statement_list END WHILE |
REPEAT | REPEAT statement_list UNTIL search_condition END REPEAT |
set @total=10;
set @res=1;
call proc_test1(@total, @res);
select @res;
sql
SELECT func(val);
SELECT * from tbl where col=func(val);
CREATE
[DEFINER = { user | CURRENT_USER}]
FUNCTION sp_name ([func_parameter[,...]])
RETURNS type
[characteristic ...] routine_body
func_parameter:
param_name type
type:
Any valid MySQL data type
characteristic:
COMMENT 'string'
| [NOT] DETERMINISTIC
routine_body:
Valid SQL routine statement
CREATE FUNCTION func_test1 (total INT)
RETURNS INT
BEGIN
DECLARE i INT;
DECLARE res INT;
SET i = 1;
SET res = 1;
IF total <= 0 THEN
SET total = 1;
END IF;
WHILE i < total DO
SET res = res * i;
SET i = i + 1;
END WHILE;
RETURN res;
END;
select func_test1(4);
SHOW CHARACTER SET;
# 编译时加入: --with-charset=
./configure --prefix=/usr/local/mysql3 --with-plugins=innobase --with-charset=gbk
查看字符序
show collation;
mysql的字符序遵从命名惯例:以_ci(表示大小写不敏感),以_CS(表示大小写敏感),以_bin(表示用编码值进行比较)。
配置文件
[mysqld]
character_set_server=utf8
collation_server=utf8_general_ci
CREATE DATABASE db_name CHARACTER SET latin1 COLLATE latin1_swedish_ci;
主要影响load data等语句的默认字符集,CREATE DATABASE的字符集如果不设置,默认使用character_set_server的字符集。
CREATE TABLE tbl1 (....) DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_bin;
CREATE TABLE tbl1 (col1 VARCHAR(5) CHARACTER SET latin1 COLLATE latin1_german1_ci);
-- 查看字符集
show [global] variables like 'character%';
show [global] variables like 'collation%';
-- 修改字符集
set global character_set_server=utf8; -- 全局
alter table xxx convert to character set xxx; -- 表
mysql > set names utf8;
配置文件设置:
[mysql]
default-character-set=utf8
client > character_set_client > character_set_connection > Storage > character_set_results >client
推荐使用统一的字符集
常见乱码原因:
使用建议
mysql CAPI:初始化数据库句柄后马上用mysql_options设定MYSQL_CHARSET_NAME属性为utf8.
JDBC客户端应用 -> java.sql.*或javax.sql.* -> 驱动程序 -> SQLserver/Oracle/MySQL
结构:
DriverManager
-> Driver(是驱动程序对象的接口,指向具体数据库驱动程序对象)=DriverManager.getDriver(String URL)
-> Connectinon(是连接对象接口,指向具体数据库连接对象)=DriverManager.getConnection(String URL)
-> Statement(执行静态SQL语句接口)=Connection.CreateStatement()
-> ResultSet(是指向结果集对象的接口)=Statement.excuteXXX()
import java.sql.*;
/**
* 使用JDBC连接MySQL
*/
public class DBTest {
public static Connection getConnection() throws SQLException,
java.lang.ClassNotFoundException
{
//第一步:加载MySQL的JDBC的驱动
Class.forName("com.mysql.jdbc.Driver");
//设置MySQL连接字符串,要访问的MySQL数据库 ip,端口,用户名,密码
String url = "jdbc:mysql://localhost:3306/blog";
String username = "blog_user";
String password = "blog_pwd";
//第二步:创建与MySQL数据库的连接类的实例
Connection con = DriverManager.getConnection(url, username, password);
return con;
}
public static void main(String args[]) {
Connection con = null;
try
{
//第三步:获取连接类实例con,用con创建Statement对象类实例 sql_statement
con = getConnection();
Statement sql_statement = con.createStatement();
/************ 对数据库进行相关操作 ************/
//如果同名数据库存在,删除
sql_statement.executeUpdate("drop table if exists user;");
//执行了一个sql语句生成了一个名为user的表
sql_statement.executeUpdate("create table user (id int not null auto_increment," +
" name varchar(20) not null default 'name', age int not null default 0, primary key (id) ); ");
//向表中插入数据
System.out.println("JDBC 插入操作:");
String sql = "insert into user(name,age) values('liming', 18)";
int num = sql_statement.executeUpdate("insert into user(name,age) values('liming', 18)");
System.out.println("execute sql : " + sql);
System.out.println(num + " rows has changed!");
System.out.println("");
//第四步:执行查询,用ResultSet类的对象,返回查询的结果
String query = "select * from user";
ResultSet result = sql_statement.executeQuery(query);
/************ 对数据库进行相关操作 ************/
System.out.println("JDBC 查询操作:");
System.out.println("------------------------");
System.out.println("userid" + " " + "name" + " " + "age ");
System.out.println("------------------------");
//对获得的查询结果进行处理,对Result类的对象进行操作
while (result.next())
{
int userid = result.getInt("id");
String name = result.getString("name");
int age = result.getInt("age");
//取得数据库中的数据
System.out.println(" " + userid + " " + name + " " + age);
}
//关闭 result,sql_statement
result.close();
sql_statement.close();
//使用PreparedStatement更新记录
sql = "update user set age=? where name=?;";
PreparedStatement pstmt = con.prepareStatement(sql);
//设置绑定变量的值
pstmt.setInt(1, 15);
pstmt.setString(2, "liming");
//执行操作
num = pstmt.executeUpdate();
System.out.println("");
System.out.println("JDBC 更新操作:");
System.out.println("execute sql : " + sql);
System.out.println(num + " rows has changed!");
//关闭PreparedStatement
pstmt.close();
//流式读取result,row-by-row
query = "select * from user";
PreparedStatement ps = (PreparedStatement) con.prepareStatement
(query,ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
ps.setFetchSize(Integer.MIN_VALUE);
result = ps.executeQuery();
/************ 对数据库进行相关操作 ************/
System.out.println("JDBC 查询操作:");
System.out.println("------------------------");
System.out.println("userid" + " " + "name" + " " + "age ");
System.out.println("------------------------");
//对获得的查询结果进行处理,对Result类的对象进行操作
while (result.next())
{
int userid = result.getInt("id");
String name = result.getString("name");
int age = result.getInt("age");
//取得数据库中的数据
System.out.println(" " + userid + " " + name + " " + age);
}
//关闭 result,ps
result.close();
ps.close();
con.close();
} catch(java.lang.ClassNotFoundException e) {
//加载JDBC错误,所要用的驱动没有找到
System.err.print("ClassNotFoundException");
//其他错误
System.err.println(e.getMessage());
} catch (SQLException ex) {
//显示数据库连接错误或查询错误
System.err.println("SQLException: " + ex.getMessage());
}
}
}
PREPARE -> EXECUTE -> DEALLOCATE PREPARE
PREPARE stmt1 FROM 'SELECT productCode, productName
From products
WHERE productCode = ?';
SET @pc = 'S10_1678';
EXECUTE stmt1 USING @pc;
DEALLOCATE PREPARE stmt1;
url=”jdbc:mysql://localhost:3306/blog_dbo?userUnicode=true&characterEncoding=utf8”;
url=”jdbc:mysql://localhost:3306/blog_dbo?connectionTimeout=1000&socketTimeout=30000”;
import MySQLdb
# 建立和mysql数据库的连接
conn = MySQLdb.connect(host='localhost', port=3306,user='bloguser',passwd='xxxx')
# 获取游标
curs = conn.cursor()
# 选择数据库
conn.select_db('blog')
# 执行SQL,创建一个表
curs.execute("create table blog (id int, name varchar(200))")
# 插入一条记录
value = [1, 'user1']
curs.execute("insert into blog values(%s, %s)", value)
# 插入多条记录
values = [(2, "user2"), (3, "user3")]
curs.executemany("insert into blog values(%s, %s)", values)
# 提交
conn.commit()
# 关闭游标
curs.close()
# 关闭连接
conn.close()
示例代码在sorence/DAO框架代码示例.rar
#{}
和${}
的不同应用场景: #{}
会生成预编译SQL,会正确的处理数据的类型,而${}
仅仅是文本替换。