安装
1 sudo apt-get update
2. sudo apt-get install mysql-serversudo apt-get update
Could not resolve 'security.ubuntu.com'
Err http://extras.ubuntu.com trusty Release.gpg Could not resolve 'extras.ubuntu.com' Err http://us.archive.ubuntu.com trusty InRelease Err http://us.archive.ubuntu.com trusty Release.gpg Could not resolve 'us.archive.ubuntu.com'从Error Message 上看来似乎是“cn.archive.ubuntu.com”域名解析出错。于是在windows cmd中里Ping了一下这个域名。发现能够Ping 通。
C:\Documents and Settings\Administrator>ping us.archive.ubuntu.com Pinging us.archive.ubuntu.com [91.189.91.14] with 32 bytes of data: Reply from 91.189.91.14: bytes=32 time=224ms TTL=47 Reply from 91.189.91.14: bytes=32 time=224ms TTL=47 Reply from 91.189.91.14: bytes=32 time=224ms TTL=47 C:\Documents and Settings\Administrator>ping security.ubuntu.com Pinging security.ubuntu.com [91.189.91.13] with 32 bytes of data: Reply from 91.189.91.13: bytes=32 time=230ms TTL=47 Reply from 91.189.91.13: bytes=32 time=235ms TTL=47 Reply from 91.189.91.13: bytes=32 time=230ms TTL=47 Reply from 91.189.91.13: bytes=32 time=230ms TTL=47 C:\Documents and Settings\Administrator>ping extras.ubuntu.com Pinging extras.ubuntu.com [91.189.92.152] with 32 bytes of data: Reply from 91.189.92.152: bytes=32 time=284ms TTL=42 Reply from 91.189.92.152: bytes=32 time=283ms TTL=42 Reply from 91.189.92.152: bytes=32 time=284ms TTL=42 Reply from 91.189.92.152: bytes=32 time=284ms TTL=42
于是尝试通过改动 /etc/hosts 解决问题:
- sudo gedit /etc/hosts
- 在文件末尾增加 91.189.92.152 extras.ubuntu.com 91.189.91.13 security.ubuntu.com 91.189.91.14 us.archive.ubuntu.com
- 执行 “#/etc/init.d/networking restart” 重新启动网络。
- 执行 “sudo apt-get update成功!!
!
sudo apt-get install mysql-server
───────────────────┤ Configuring mysql-server-5.5 ├─────────────────────┐ │ While not mandatory, it is highly recommended that you set a password │ │ for the MySQL administrative "root" user. │ │ │ │ If this field is left blank, the password will not be changed. │ │ │ │ New password for the MySQL "root" user: │ │ │ │ _______________________________________________________________________ │ │ │ │ <Ok> 输入1 而且确认,就是root的password了Setting up libhtml-template-perl (2.95-1) ...
Processing triggers for ureadahead (0.100.0-16) ... Setting up mysql-server (5.5.43-0ubuntu0.14.04.1) ... Processing triggers for libc-bin (2.19-0ubuntu6.5) ...sudo apt-get install mysql-client
Preparing to unpack .../mysql-client_5.5.43-0ubuntu0.14.04.1_all.deb ... Unpacking mysql-client (5.5.43-0ubuntu0.14.04.1) ... Setting up mysql-client (5.5.43-0ubuntu0.14.04.1) ...sudo apt-get install libmysqlclient-dev
Processing triggers for man-db (2.6.7.1-1ubuntu1) ...
Setting up zlib1g-dev:i386 (1:1.2.8.dfsg-1ubuntu1) ... Setting up libmysqlclient-dev (5.5.43-0ubuntu0.14.04.1) ... 至此安装完成检查是否成功安装
sudo netstat -tap | grep mysql
a@ubuntu:~$ sudo netstat -tap | grep mysql
tcp 0 0 localhost:mysql *:* LISTEN 6911/mysqld 说明是成功的 port在LISTEN状态登陆mysql数据库
查看当前的数据库
show databases;
mysql> show databases -> ; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | +--------------------+ 3 rows in set (0.00 sec)
使用数据库
use mysql
mysql> use mysql
Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed 显示数据表单show tables
mysql> show tables;
+---------------------------+ | Tables_in_mysql | +---------------------------+ | columns_priv | | db | | event | | func | | general_log | | help_category | | help_keyword | | help_relation | | help_topic | | host | | ndb_binlog_index | | plugin | | proc | | procs_priv | | proxies_priv | | servers | | slow_log | | tables_priv | | time_zone | | time_zone_leap_second | | time_zone_name | | time_zone_transition | | time_zone_transition_type | | user | +---------------------------+ 24 rows in set (0.00 sec)程序訪问该数据库
insert
#include<stdio.h>
#include<string.h>
#include "mysql.h"
int main()
{
MYSQL mysql;
char f1[100];
int f2;
char host[100];
char user[100];
char pwd[100];
char db[100];
int port;
char query[1000];
char yn;
printf("Please enter the host:\n");
scanf("%s",host);
printf("Please enter the username:\n");
scanf("%s",user);
printf("Please enter the password:\n");
scanf("%s",pwd);
printf("Please select a database:\n");
scanf("%s",db);
printf("Please enter the tcp port:\n");
scanf("%d",&port);
mysql_init(&mysql);
if(mysql_real_connect(&mysql, host, user, pwd, db, port, NULL, 0))
{
printf("Please enter the f1:\n");
scanf("%s",f1);
printf("Please enter the f2:\n");
scanf("%d",&f2);
getchar();
sprintf(query, "INSERT INTO test (id, test1, test2) VALUES (null, '%s', '%d')", f1,f2);
if(!mysql_real_query(&mysql,query,strlen(query)))
{
printf("Insert successed!!!\n");
printf("Whether to print the last SQL:(y/n)");
scanf("%c",&yn);
if(yn=='y')
{
printf("%s\n",query);
mysql_close(&mysql);
}
else
{
mysql_close(&mysql);
return;
}
}
else
{
printf("Insert failed!!!\n");
}
}
else
{
printf("Connect to MySQL failed!!!\n");
}
}
delete
#include<stdio.h>
#include<string.h>
#include "mysql.h" int main() { MYSQL mysql; char host[100]; char user[100]; char pwd[100]; char db[100]; int port; char query[1000]; char yn; int id; printf("Please enter the host:\n"); scanf("%s",host); printf("Please enter the username:\n"); scanf("%s",user); printf("Please enter the password:\n"); scanf("%s",pwd); printf("Please select a database:\n"); scanf("%s",db); printf("Please enter the tcp port:\n"); scanf("%d",&port); mysql_init(&mysql); if(mysql_real_connect(&mysql, host, user, pwd, db, port, NULL, 0)) { printf("Please enter the id which you want to delete:\n"); scanf("%d",&id); getchar(); sprintf(query, "DELETE FROM test WHERE id=%d", id); if(!mysql_real_query(&mysql,query,strlen(query))) { printf("Delete successed!!!\n"); printf("Whether to print the last SQL:(y/n)"); scanf("%c",&yn); if(yn=='y') { printf("%s\n",query); mysql_close(&mysql); } else { mysql_close(&mysql); return; } } else { printf("Delete failed!!!\n"); } } else { printf("Connect to MySQL failed!!!\n"); } }update
#include<stdio.h>
#include<string.h>
#include "mysql.h" int main() { MYSQL mysql; char host[100]; char user[100]; char pwd[100]; char db[100]; int port; char query[1000]; char f1[100]; int f2; char yn; int id; printf("Please enter the host:\n"); scanf("%s",host); printf("Please enter the username:\n"); scanf("%s",user); printf("Please enter the password:\n"); scanf("%s",pwd); printf("Please select a database:\n"); scanf("%s",db); printf("Please enter the tcp port:\n"); scanf("%d",&port); mysql_init(&mysql); if(mysql_real_connect(&mysql, host, user, pwd, db, port, NULL, 0)) { printf("Please enter the content you want to modify on test1:\n"); scanf("%s",f1); printf("Please enter the content you want to modify on test2:\n"); scanf("%d",&f2); printf("Please select one id which you want to modify:\n"); scanf("%d",&id); getchar(); sprintf(query, "UPDATE test SET test1='%s', test2='%d' WHERE id=%d", f1,f2,id); if(!mysql_real_query(&mysql,query,strlen(query))) { printf("Delete successed!!!\n"); printf("Whether to print the last SQL:(y/n)"); scanf("%c",&yn); if(yn=='y') { printf("%s\n",query); mysql_close(&mysql); } else { mysql_close(&mysql); return; } } else { printf("Delete failed!!!\n"); } } else { printf("Connect to MySQL failed!!!\n"); } }select
#include<stdio.h>
#include<string.h>
#include "mysql.h" int main() { MYSQL mysql; MYSQL_RES *res; MYSQL_ROW row; char f1[100]; char f2[100]; char host[100]; char user[100]; char pwd[100]; char db[100]; int port; char query[1000]; char yn; int id; printf("Please enter the host:\n"); scanf("%s",host); printf("Please enter the username:\n"); scanf("%s",user); printf("Please enter the password:\n"); scanf("%s",pwd); printf("Please select a database:\n"); scanf("%s",db); printf("Please enter the tcp port:\n"); scanf("%d",&port); mysql_init(&mysql); if(mysql_real_connect(&mysql, host, user, pwd, db, port, NULL, 0)) { printf("Please enter the f1:\n"); scanf("%s",f1); printf("Please enter the f2:\n"); scanf("%s",&f2); printf("Please enter a id which you want to find:\n"); scanf("%d",&id); getchar(); sprintf(query, "SELECT %s,%s FROM test WHERE id=%d", f1,f2,id); if(!mysql_real_query(&mysql,query,strlen(query))) { res=mysql_store_result(&mysql); while(row=mysql_fetch_row(res)) { printf("%-12s",row[0]); printf("%12s",row[1]); printf("\n"); } printf("Whether to print the last SQL:(y/n)"); scanf("%c",&yn); if(yn=='y') { printf("%s\n",query); mysql_close(&mysql); } else { mysql_close(&mysql); return; } } else { printf("Select failed!!!\n"); } } else { printf("Connect to MySQL failed!!!\n"); } }样例1 show tables
写一个简单的程序来訪问该数据库,实现 show tables 功能:
代码
#include <mysql/mysql.h>
#include <stdio.h> #include <stdlib.h> int main() { MYSQL *conn; MYSQL_RES *res; MYSQL_ROW row; char server[] = "localhost"; char user[] = "root"; char password[] = "1"; char database[] = "mysql"; conn = mysql_init(NULL); if (!mysql_real_connect(conn, server,user, password, database, 0, NULL, 0)) { fprintf(stderr, "%s\n", mysql_error(conn)); exit(1); } if (mysql_query(conn, "show tables")) { fprintf(stderr, "%s\n", mysql_error(conn)); exit(1); } res = mysql_use_result(conn); printf("MySQL Tables in mysql database:\n"); while ((row = mysql_fetch_row(res)) != NULL) { printf("%s \n", row[0]); } mysql_free_result(res); mysql_close(conn); printf("finish! \n"); return 0; }编译
编译代码的时候须要链接mysql的库,能够通过例如以下方式编译:
gcc -Wall sqltest.c -o sqltest -lmysqlclient
然后执行编译好的代码:
a@ubuntu:~/db$ gcc -Wall sqltest.c -o sqltest -lmysqlclient运行
a@ubuntu:~/db$ sudo ./sqltest
MySQL Tables in mysql database: columns_priv db event func general_log help_category help_keyword help_relation help_topic host ndb_binlog_index plugin proc procs_priv proxies_priv servers slow_log tables_priv time_zone time_zone_leap_second time_zone_name time_zone_transition time_zone_transition_type user finish!样例2 select * from table
代码
#include <stdlib.h > #include <stdio.h > #include <mysql/mysql.h > #include <syslog.h >编译
假定mysql的头文件在/usr/include/mysql,库文件在/usr/lib/mysql,运行下列命令进行编译:
gcc -gtestsql.c -I/usr/include/mysql -L/usr/lib/mysql -lmysqlclient -lz
样例5
在linux上安装好mysql后,建立我们測试用的数据库和表,并插入记录,sql语句例如以下:
- CREATE DATABASE ta;
- use ta
- CREATE TABLE t1 (
- id INTEGER NOT NULL ,
- name TEXT NOT NULL
- );
- INSERT INTO t1 VALUES(1,'n1');
- INSERT INTO t1 VALUES(2,'n2');
- INSERT INTO t1 VALUES(3,'n3');
获得表中的记录,用到下面mysql的API:
mysql_init()
mysql_real_connect()
mysql_real_query()
mysql_store_result()
mysql_fetch_row()
mysql_free_result()
mysql_close()
操作中须要用到mysql中定义的三个结构体
MYSQL
MYSQL_RES
MYSQL_ROW
一般步骤是:
1.调用mysql_init()初始化MYSQL结构。很多的函数运行须要这个结构体。
2.调用mysql_real_connect()连接数据库。參数中涉及到数据库名。数据库登录名,数据库password等等。
3.调用mysql_real_query()运行一条Select SQL语句。通过mysql_store_result()的返回值获得Select的结果,返回的结果就是一个MYSQL_RES结构的指针。
4.调用mysql_fetch_row()获得一条记录。函数的返回值是MYSQL_ROW对象。这是一个char二维数组。
获取一条记录以后,mysql_fetch_row会将游标自己主动向下移动一条记录。
5.调用mysql_free_result()释放结果资源。调用mysql_close关闭连接。
简单的代码例如以下(没有做失败推断):
- #include <mysql/mysql.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- int main()
- {
- MYSQL mysql;
- mysql_init(&mysql);
- mysql_real_connect(&mysql,NULL,"root","123","ta",0,NULL,0);
- mysql_real_query(&mysql,"select * from t1",16);
- MYSQL_RES* res = mysql_store_result(&mysql);
- int num_fields = mysql_num_fields(res);
- MYSQL_ROW row;
- while((row = mysql_fetch_row(res)))
- {
- int i;
- for(i = 0; i < num_fields; i ++)
- {
- char buf[100];
- sprintf(buf,"[%s]",row[i]?row[i]:"NULL");
- fprintf(stdout,buf);
- }
- fprintf(stdout,"/n");
- }
- mysql_free_result(res);
- mysql_close(&mysql);
- exit(0);
- }
样例6
代码
#include <mysql/mysql.h>
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char out[100]; MYSQL mysql; MYSQL_RES* res; int num_fields; int count_fields; int num_rows; mysql_init(&mysql); mysql_real_connect(&mysql,NULL,"root","123","ta",0,NULL,0); fprintf(stdout,"--insert------------------------/n"); mysql_real_query(&mysql,"INSERT INTO t1 VALUES(6,'n6')",29); count_fields = mysql_field_count(&mysql); sprintf(out,"insert----count_fields is %d/n",count_fields); fprintf(stdout,out); res = mysql_store_result(&mysql); if(res == NULL) { fprintf(stdout,"insert---store return null/n"); } else { num_fields = mysql_num_fields(res); sprintf(out,"insert---num_fields is %d/n",num_fields); fprintf(stdout,out); } fprintf(stdout,"---select-----------/n"); mysql_real_query(&mysql,"SELECT * FROM t1",16); count_fields = mysql_field_count(&mysql); sprintf(out,"select---count_fields is %d/n",count_fields); fprintf(stdout,out); res = mysql_store_result(&mysql); if(res == NULL) { fprintf(stdout,"select---store return null/n"); } else { num_fields = mysql_num_fields(res); sprintf(out,"select---num_fields is %d/n",num_fields); fprintf(stdout,out); num_rows = mysql_num_rows(res); sprintf(out,"select---num_rows is %d/n",num_rows); fprintf(stdout,out); } fprintf(stdout,"---select 0------/n"); mysql_real_query(&mysql,"SELECT * FROM t1 where id = 10",30); count_fields = mysql_field_count(&mysql); sprintf(out,"select 0---count_fields is %d/n",count_fields); fprintf(stdout,out); res = mysql_store_result(&mysql); if(res == NULL) { fprintf(stdout,"select 0---store return null/n"); } else { num_fields = mysql_num_fields(res); sprintf(out,"select 0---num_fields is %d/n",num_fields); fprintf(stdout,out); num_rows = mysql_num_rows(res); sprintf(out,"select 0---num_rows is %d/n",num_rows); fprintf(stdout,out); } mysql_free_result(res); mysql_close(&mysql); exit(0); }运行结果是:
--insert------------------------
insert----count_fields is 0 insert---store return null ---select----------- select---count_fields is 2 select---num_fields is 2 select---num_rows is 7 ---select 0------ select 0---count_fields is 2 select 0---num_fields is 2 select 0---num_rows is 0
显然,当运行insert语句的时候,是没有结果返回的,因此列的个数为0,且mysql_store_result返回NULL。
因此能够通过mysql_field_count()是否返回0来推断是否有结果返回,而不须要运行mysql_store_result来推断是否返回了NULL。我想,mysql_field_count()的效率肯定要比mysql_store_result()高。
在这样的情况下,因为没有返回结果,因此mysql_store_result()返回NULL。也就是得不到res指针,于是mysql_num_fields()函数就无法运行,缺少必要的參数。
当运行第一条select语句的时候。返回了结果,因此mysql_field_count()和mysql_num_fields()都返回了正确的列的个数2,mysql_num_rows()返回了记录的条数7.
当运行第二条select语句。因为表中没有 id = 0 的记录,因此mysql_num_rows返回了0表示记录数为0,可是,我们发现mysql_store_result()并没有返回NULL,mysql_num_fields()和mysql_field_count()还是返回了2.
因此我们能够得出这种结论:
运行结果有三种情况,第一是运行insert、update和delete这种语句的时候,是不会有不论什么内容返回。因此mysql_store_result()会返回一个NULL。
第二。运行select或show这种语句时,一定会有内容返回。能够取得列信息,可是记录能够为0,也能够不为0。这就像一个表。表头一定存在。可是表中能够没有数据。
另外:
mysql_affected_rows()函数的作用是,当运行update insert delete 时。返回影响的行数。
Mysql库函数说明
变量及结构体
MYSQL
MYSQL是用来连接数据库的通讯过程。要连接MYSQL,必须建立MYSQL实例,通过mysql_init初始化方能開始进行连接。
这个结构代表返回行的一个查询的(SELECT, SHOW, DESCRIBE, EXPLAIN)的结果
typedef struct st_mysql { NET net; /* Communication parameters */ gptr connector_fd; /* ConnectorFd for SSL */ char *host,*user,*passwd,*unix_socket, *server_version,*host_info,*info,*db; unsigned int port,client_flag,server_capabilities; unsigned int protocol_version; unsigned int field_count; unsigned int server_status; unsigned long thread_id; /* Id for connection in server */ my_ulonglong affected_rows; my_ulonglong insert_id; /* id if insert on table with NEXTNR */ my_ulonglong extra_info; /* Used by mysqlshow */ unsigned long packet_length; enum mysql_status status; MYSQL_FIELD *fields; MEM_ROOT field_alloc; my_bool free_me; /* If free in mysql_close */ my_bool reconnect; /* set to 1 if automatic reconnect */ struct st_mysql_options options; char scramble_buff[9]; struct charset_info_st *charset; unsigned int server_language; } MYSQL; |
MYSQL_RES
返回的数据称为“数据集”,在C的API里相应的就是MYSQL_RES了。从数据库读取数据,最后就是从MYSQL_RES中读取数据。
typedef struct st_mysql_res { my_ulonglong row_count; unsigned int field_count, current_field; MYSQL_FIELD *fields; MYSQL_DATA *data; MYSQL_ROWS *data_cursor; MEM_ROOT field_alloc; MYSQL_ROW row; /* If unbuffered read */ MYSQL_ROW current_row; /* buffer to current row */ unsigned long *lengths; /* column lengths of current row */ MYSQL *handle; /* for unbuffered reads */ my_bool eof; /* Used my mysql_fetch_row */ } MYSQL_RES; |
MYSQL_ROW
是一个行数据的类型安全(type-safe)的表示。当前它实现为一个计数字节的字符串 数组。 (假设字段值可能包括二进制数据,你不能将这些视为空终止串,由于这种值能够在内部包括空字节) 行通过调用mysql_fetch_row()获得
typedef char** MYSQL_ROW; |
MYSQL_FIELD
这个结构包括字段信息,比如字段名、类型和大小。其成员在以下更具体地描写叙述。
你能够通过反复调用mysql_fetch_field()对每一列获得MYSQL_FIELD 结构。
字段值不是这个结构的部分。他们被包括在一个MYSQL_ROW 结构中
typedef struct st_mysql_field { char *name; /* Name of column */ char *table; /* Table of column if column was a field */ char *def; /* Default value (set by mysql_list_fields) */ enum enum_field_types type; /* Type of field. Se mysql_com.h for types */ unsigned int length; /* Width of column */ unsigned int max_length; /* Max width of selected set */ unsigned int flags; /* Div flags */ unsigned int decimals; /* Number of decimals in field */ } MYSQL_FIELD |
My_ulonglong
该类型用于行编号和 mysql_affected_rows ()、mysql_num_rows()和 mysql_insert_id()。这种类型提供 0 到 1.84e19 的一个范围。在一些系统上。试图打印类 型 my_ulonglong 的值将不工作。为了打印出这种值。将它变换到 unsigned long 而且使 用一个%lu 打印格式。
typedef unsigned long my_ulonglong; |
函数
1 mysql_init
1) 所需头文件: #include <mysql/mysql.h>
2) 功能: 获得或初始化一个MYSQL结构
3) 函数原型: MYSQL *mysql_init(MYSQL *mysql)
4) 函数返回值: 一个被始化的MYSQL*句柄
5) 备注: 在内存不足的情况下。返回NULL
2 mysql_close
1) 所需头文件: #include <mysql/mysql.h>
2) 函数功能: 关闭一个server连接,并释放与连接相关的内存
3) 函数原型: void mysql_close(MYSQL *mysql);
4) 函数传入值: MYSQL类型的指针
5) 函数返回值: 无
3 mysql_connect
1) 所需头文件: #include <mysql/mysql.h>
2) 函数功能: 连接一个MySQLserver
3) 函数原型: MYSQL * mysql_connect(MYSQL *mysql,const char *host,const char *user,const char *passwd);
4) 函数传入值: mysql表示一个现存mysql结构的地址
host表示MYSQLserver的主机名或IP user表示登录的username passwd表示登录的password5) 函数返回值: 假设连接成功,一个MYSQL *连接句柄:假设连接失败,NULL
6) 备注: 该函数不推荐。使用mysql_real_connect()取代
4 mysql_real_connect
1) 所需文件: #include <mysql/mysql.h>
2) 函数功能:连接数据库
3) 函数原型:MYSQL *mysql_real_connect(MYSQL *mysql,const char *host,const char *user,const char *passwd,const char *db,unsigned int port,const char *unix_socket,unsigned int client_flag);
4) 函数传入值: mysql表示一个现存mysql结构的地址
host表示MYSQLserver的主机名或IP user表示登录的username passwd表示登录的password db表示要连接的数据库 port表示MySQLserver的TCP/IP端口 unix_socket表示连接类型 client_flag表示MySQL执行ODBC数据库的标记注:
參数的指定方式例如以下:
第1个參数应是已有MYSQL结构的地址。
调用mysql_real_connect()之前,必须调用mysql_init()来初始化MYSQL结构。通过mysql_options()调用,可更改多种连接选项。
“host”的值必须是主机名或IP地址。
假设“host”是NULL或字符串"localhost"。连接将被视为与本地主机的连接。假设操作系统支持套接字(Unix)或命名管道(Windows)。将使用它们而不是TCP/IP连接到server。
“user”參数包括用户的MySQL登录ID。假设“user”是NULL或空字符串""。用户将被视为当前用户。
在UNIX环境下,它是当前的登录名。在Windows ODBC下。必须明白指定当前username。
“passwd”參数包括用户的password。假设“passwd”是NULL。仅会对该用户的(拥有1个空password字段的)用户表中的条目进行匹配检查。这样。数据库管理员就能按特定的方式设置MySQL权限系统,依据用户是否拥有指定的password,用户将获得不同的权限。
调用mysql_real_connect()之前。不要尝试加密password,password加密将由clientAPI自己主动处理。
“db”是数据库名称。假设db为NULL。连接会将默认的数据库设为该值。
假设“port”不是0,其值将用作TCP/IP连接的端口号。注意,“host”參数决定了连接的类型。
假设unix_socket不是NULL,该字符串描写叙述了应使用的套接字或命名管道。注意,“host”參数决定了连接的类型。
client_flag的值通常为0。可是,也能将其设置为下述标志的组合,以同意特定功能:
标志名称 | 标志描写叙述 |
CLIENT_COMPRESS | 使用压缩协议。 |
CLIENT_FOUND_ROWS | 返回发现的行数(匹配的)。而不是受影响的行数。 |
CLIENT_IGNORE_SPACE | 同意在函数名后使用空格。使全部的函数名成为保留字。 |
CLIENT_INTERACTIVE | 关闭连接之前。同意interactive_timeout秒的不活动时间。 |
CLIENT_LOCAL_FILES | 同意LOAD DATA LOCAL处理功能。 |
CLIENT_MULTI_STATEMENTS | 通知server,client可能在单个字符串内发送多条语句。使用该标识能够获取多个查询结果 |
CLIENT_MULTI_RESULTS | 通知server,client可以处理来自多语句运行。 |
CLIENT_NO_SCHEMA | 禁止db_name.tbl_name.col_name语法。 |
CLIENT_ODBC | client是ODBCclient。它将mysql变得更为ODBC友好。 |
CLIENT_SSL | 使用SSL,该选项不应由应用程序设置,而是在client库内部设置。 |
5) 函数返回值: 假设连接成功。返回与第一个參数值同样的一个MYSQL*连接句柄:假设连接失败。返回NULL。通过mysql_error()获取出错原因。
5 mysql_affected_rows
1) 所需头文件: #include <mysql/mysql.h>
2) 函数功能: 返回最新的UPDATE,DELETE或INSERT查询影响的行数
3) 函数原型:mysql_affected_rows(MYSQL *mysql)
4) 函数传入值: MYSQL类型指针
5) 函数返回值: 大于零的一个整数表示受到影响或检索出来的行数。零表示没有区配查序中WHERE子句的记录或眼下还没有查询被运行;-1表示查询返回一个错误,或对于一个SELECT查询
6 mysql_query
1) 所需头文件: #include <mysql/mysql.h>
2) 函数功能: 对指定的连接运行查询
3) 函数原型: int mysql_query(MYSQL *mysql,const char *query);
4) 函数传入值: query表示运行的SQL语句
5) 函数返回值: 假设查询成功,为零。出错为非零。
6) 相关函数: mysql_real_query
7 Mysql_real_query
1) 所需头文件: #include <mysql/mysql.h>
2) 函数功能:对指定的连接运行查询
3) 函数原型: int mysql_real_query(MYSQL *mysql,const char *query,unsigned int length);
4) 函数传入值: query表示运行的SQL语句
Length表示SQL语句的长度
5) 函数返回值: 假设查询成功,为零。出错为非零。出错的代码及原因例如以下所看到的:
出错代码 | 原因 |
CR_COMMANDS_OUT_OF_SYNC | 命令以一个不适当的次序被运行。 |
CR_SERVER_GONE_ERROR | MySQLserver关闭了。 |
CR_SERVER_LOST | 对server的连接在查询期间失去。 |
CR_UNKNOWN_ERROR | 发生一个未知的错误 |
6) 备注:对于包括二进制数据的查询,使用mysql_real_query()而不是mysql_query(),由于二进制代码数据可能包括“\0”字符,并且。mysql_real_query()比mysql_query()更快,由于它对查询字符串调用strlen()。
8 mysql_store_result
1) 所需头文件: #include <mysql/mysql.h>
2) 函数功能:获取结果标识符
3) 函数原型: MYSQL_RES *mysql_store_result(MYSQL *mysql);
4) 函数传入值: MYSQL:类型的指针
5) 函数返回值: 一个MYSQL_RES结果结构。假设发生一个错误发NULL
6) 备注:
假设希望了解查询是否应返回结果集。可使用mysql_field_count()进行检查。“mysql_field_count()”。mysql_store_result()将查询的所有结果读取到client,分配1个MYSQL_RES结构,并将结果置于该结构中。
假设查询未返回结果集,mysql_store_result()将返回Null指针(比如。假设查询是INSERT语句)。
假设读取结果集失败,mysql_store_result()还会返回Null指针。通过检查mysql_error()是否返回非空字符串,mysql_errno()是否返回非0值,或mysql_field_count()是否返回0,能够检查是否出现了错误。假设未返回行,将返回空的结果集。(空结果集设置不同于作为返回值的空指针)。
一旦调用了mysql_store_result()并获得了不是Null指针的结果,可调用mysql_num_rows()来找出结果集中的行数。
能够调用mysql_fetch_row()来获取结果集中的行,或调用mysql_row_seek()和mysql_row_tell()来获取或设置结果集中的当前行位置。一旦完毕了对结果集的操作,必须调用mysql_free_result()。
9 mysql_use_result
1) 所需头文件: #include <mysql/mysql.h>
2) 函数功能: 为无缓冲的结果集获得结果标识符
3) 函数原型: MYSQL_RES *mysql_use_result(MYSQL *mysql);
4) 函数传入值: MYSQL类型的指针
5) 函数返回值: 一个MYSQL_RES结果结构,假设发生一个错误发NULL
6) 备注:
mysql_use_result()将初始化结果集检索,但并不像mysql_store_result()那样将结果集实际读取到client。它必须通过对mysql_fetch_row()的调用。对每一行分别进行检索。这将直接从server读取结果,而不会将其保存在暂时表或本地缓冲区内,与mysql_store_result()相比,速度更快并且使用的内存也更少。
client仅为当前行和通信缓冲区分配内存,分配的内存可添加到max_allowed_packet字节。
使用mysql_use_result()时。必须运行mysql_fetch_row(),直至返回NULL值,否则,未获取的行将作为下一个检索的一部分返回。
C API给出命令不同步错误。假设忘记了运行该操作,将不能运行该命令。不应与从mysql_use_result()返回的结果一起使用mysql_data_seek()、mysql_row_seek()、mysql_row_tell()、mysql_num_rows()或mysql_affected_rows(),也不应发出其它查询,直至mysql_use_result()完毕为止。(可是。提取了全部行后,mysql_num_rows()将准确返回提取的行数)。一旦完毕了对结果集的操作,必须调用mysql_free_result()。
10 mysql_fetch_row
1) 所需头文件: #include <mysql/mysql.h>
2) 函数功能: 检索一个结果集合的下一行
3) 函数原型:MYSQL_ROW mysql_fetch_row(MYSQL_RES *result);
4) 函数传入值:MYSQL_RES:结构的指针
5) 函数返回值: 下一行的一个MYSQL_ROW结构。假设没有很多其它的行可检索或假设出现一个错误。NULL
11 mysql_field_count
1) 所需头文件: #include <mysql/mysql.h>
2) 函数功能: 返回近期查询的列数
3) 函数原型:unsigned int mysql_field_count(MYSQL *mysql);
4) 函数传入值:MYSQL类型的指针
5) 函数返回值: 结果集中列数的无符号整数
12 mysql_num_fields
1) 所需头文件: #include <mysql/mysql.h>
2) 函数功能: 返回指定结果集中列的数量
3) 函数原型:unsigned int mysql_num_fields(MYSQL_RES *res);
4) 函数传入值:MYSQL_RES 结构的指针
5) 函数返回值: 结果集合中字段数量的一个无符号整数
13 mysql_create_db
1) 所需头文件: #include <mysql/mysql.h>
2) 函数功能: 创建一个数据库
3) 函数原型:int mysql_create_db(MYSQL *mysql,const char *db);
4) 函数传入值:MYSQL:类型的指针
db:要创建的数据库名5) 函数返回值: 假设数据库成功地被创建。返回零,假设错误发生,为非零。
14 mysql_select_db
1) 所需头文件: #include <mysql/mysql.h>
2) 函数功能: 选择一个数据库
3) 函数原型:int mysql_select_db(MYSQL *mysql,const char *db);
4) 函数传入值:MYSQL:类型的指针
db:要创建的数据库名5) 函数返回值: 假设数据库成功地被创建,返回零,假设错误发生,为非零。
举例
#include <stdio.h> #include <stdlib.h> #include "mysql.h" //242机器上该文件在/usr/include/mysql下 //定义数据库操作的宏。也能够不定义留着后面直接写进代码 #define SELECT_QUERY "select username from tbb_user where userid = %d" int main(int argc, char **argv) //char **argv 相当于 char *argv[] { MYSQL mysql,*sock; //定义数据库连接的句柄。它被用于差点儿全部的MySQL函数 MYSQL_RES *res; //查询结果集。结构类型 MYSQL_FIELD *fd ; //包括字段信息的结构 MYSQL_ROW row ; //存放一行查询结果的字符串数组 char qbuf[160]; //存放查询sql语句字符串 if (argc != 2) { //检查输入參数 fprintf(stderr,"usage : mysql_select <userid>\n\n"); exit(1); } mysql_init(&mysql);if (!(sock = mysql_real_connect(&mysql,"localhost","dbuser","dbpwd","9tmd_bbs_utf8",0,NULL,0))) { fprintf(stderr,"Couldn't connect to engine!\n%s\n\n",mysql_error(&mysql)); perror(""); exit(1); } sprintf(qbuf,SELECT_QUERY,atoi(argv[1])); if(mysql_query(sock,qbuf)) { fprintf(stderr,"Query failed (%s)\n",mysql_error(sock)); exit(1); } if (!(res=mysql_store_result(sock))) { fprintf(stderr,"Couldn't get result from %s\n", mysql_error(sock)); exit(1); } printf("number of fields returned: %d\n",mysql_num_fields(res)); while (row = mysql_fetch_row(res)) { printf("Ther userid #%d 's username is: %s\n", atoi(argv[1]),(((row[0]==NULL)&&(!strlen(row[0]))) ?"NULL" : row[0])) ; puts( "query ok !\n" ) ; } mysql_free_result(res); mysql_close(sock); exit(0); return 0; //. 为了兼容大部分的编译器增加此行 } |
编译及执行
使用以下的命令编译
gcc -o demo ./demo.c -I/usr/include/mysql -L/usr/lib64/mysql -lmysqlclient (-lz) (-lm) 后面两个选项可选 |
使用以下的命令执行
./demo |
mysql中文文档:
SQL备份
MySQL中的每个数据库和数据表分别相应文件系统中的文件夹和其下的文件。
在Linux下数据库文件的存放文件夹一般为/var/lib/mysql
方法一:拷贝
备份文件前。须要将MySQL服务停止,然后将数据库文件夹拷贝就可以。
恢复数据数据库时。须要先创建好一个数据库(不一定同名)。然后将备份出来的文件(注意,不是文件夹)拷贝到相应的MySQL数据库文件夹中。 使用这一方法备份和恢复数据库时,须要新旧的MySQL版本号一致,否则可能会出现错误。方法二:mysqldump
备份数据库:mysqldump –user=root –password=root密码 –lock-all-tables 数据库名 > 备份文件.sql
恢复数据库:mysql -u root –password=root密码 数据库名 < 备份文件.sql
方法三:脚本定时备份
把MySql数据库存放文件夹/var/lib/mysql以下的pw85数据库备份到/home/mysql_data里面,而且保存为mysqldata_bak_2012_04_11.tar.gz的压缩文件格式(2012_04_11是指备份运行时当天的日期)。 最后仅仅保留近期7天的备份。
每天你在/home/mysql_data文件夹以下能够看到类似mysqldata_bak_2012_04_11.tar.gz这种压缩文件。假设须要恢复文件的时候,仅仅须要把这个文件解压:tar -zxvf mysqldata_bak_2012_04_11.tar.gz然后导入到数据库中就可以。
1、创建保存备份文件的文件夹:
/home/mysql_datacd /home #进入文件夹
mkdir mysql_data #创建文件夹2、创建备份脚本文件
:/home/mysql_data/mysql_databak.sh
cd /home/mysql_data #进入文件夹 touch mysql_databak.sh #创建文件nano mysql_databak.sh #编辑文件。输入下面内容3、改动文件属性,使其可运行
chmod +x /home/mysql_data/mysql_databak.sh
4、改动/etc/crontab
nano /etc/crontab #编辑文件,在以下加入
45 22 * * * root /home/mysql_data/mysql_databak.sh #表示每天22点45分运行备份 ctrl+o #保存配置 ctrl+x #退出5、又一次启动crond使设置生效
service cron stop #停止
service cron start #启动 /etc/init.d/cron restart #重新启动 chkconfig cron on #设为开机启动/home/mysql_data/mysql_databak.sh内容例如以下:
#!/bin/sh
DUMP=/usr/bin/mysqldump #mysqldump备份程序运行路径 OUT_DIR=/home/mysql_data #备份文件存放路径 LINUX_USER=root #系统username DB_NAME=pw85 #要备份的数据库名字 DB_USER=root #数据库账号 注意:非root用户要用备份參数 --skip-lock-tables,否则可能会报错 DB_PASS=123456 #数据库password DAYS=7 #DAYS=7代表删除7天前的备份,即仅仅保留近期7天的备份 cd $OUT_DIR #进入备份存放文件夹 DATE=`date +%Y_%m_%d` #获取当前系统时间 OUT_SQL="$DATE.sql" #备份数据库的文件名称 TAR_SQL="mysqldata_bak_$DATE.tar.gz" #终于保存的数据库备份文件名称 $DUMP -u$DB_USER -p$DB_PASS $DB_NAME --default-character-set=utf8 --opt -Q -R --skip-lock-tables> $OUT_SQL #备份 tar -czf $TAR_SQL ./$OUT_SQL #压缩为.tar.gz格式 rm $OUT_SQL #删除.sql格式的备份文件 chown $LINUX_USER:$LINUX_USER $OUT_DIR/$TAR_SQL #更改备份数据库文件的全部者 find $OUT_DIR -name "mysqldata_bak*" -type f -mtime +$DAYS -exec rm {} \; #删除7天前的备份文件备份数据库常见命令
备份MySQL数据库的命令
mysqldump -hhostname -uusername -ppassword databasename > backupfile.sql
备份MySQL数据库为带删除表的格式备份MySQL数据库为带删除表的格式,可以让该备份覆盖已有数据库而不须要手动删除原有数据库。
mysqldump ---add-drop-table -uusername -ppassword databasename > backupfile.sql
直接将MySQL数据库压缩备份
mysqldump -hhostname -uusername -ppassword databasename | gzip > backupfile.sql.gz
备份MySQL数据库某个(些)表
mysqldump -hhostname -uusername -ppassword databasename specific_table1 specific_table2 > backupfile.sql
同一时候备份多个MySQL数据库
mysqldump -hhostname -uusername -ppassword --databases databasename1 databasename2 databasename3 > multibackupfile.sql
只备份数据库结构
mysqldump --no-data --databases databasename1 databasename2 databasename3 > structurebackupfile.sql
备份server上全部数据库
mysqldump --all-databases allbackupfile.sql
还原MySQL数据库的命令
mysql -hhostname -uusername -ppassword databasename < backupfile.sql
还原压缩的MySQL数据库
gunzip < backupfile.sql.gz | mysql -uusername -ppassword databasename
将数据库转移到新server
mysqldump \-uusername \-ppassword databasename \| mysql \--host=*.*.*.\* \-C databasename
压缩备份
备份并用gzip压缩:
mysqldump < mysqldump options> | gzip > outputfile.sql.gz
从gzip备份恢复:
gunzip < outputfile.sql.gz | mysql < mysql options>
备份并用bzip压缩:
mysqldump < mysqldump options> | bzip2 > outputfile.sql.bz2
从bzip2备份恢复:
bunzip2 < outputfile.sql.bz2 | mysql < mysql options>
启动停止重新启动mysql
启动
sudo
/etc/init
.d
/mysql
start
停止
sudo
/etc/init
.d
/mysql
stop
重新启动
sudo
/etc/init
.d
/mysql
restart
查看日志
cat
/var/log/mysql
.err
cat
/var/log/mysql/error
.log
不支持中文
改动 /etc/mysql/my.cnf
在 [client] 以下添加:
default-character-set=utf8 或 character_set_server=utf8
在 [mysqld] 以下添加:
default-character-set=utf8 或 character_set_server=utf8
错误提示:
unknown variable 'default-character-set=utf8'
改动配置文件 /etc/mysql/my.cnf 中的“default-character-set=utf8” 为 “character_set_server=utf8”
mysql操作
1. Mysql基本操作
1.1 改动管理员的password
1) Mysql刚安装好后无password,使用”mysqladmin–uroot password password”改动管理员password
2) 以管理员身份登录数据库,使用”mysql–u root”
3) 原来有password,如今要改动,使用”mysqladmin–uroot–p旧password password 新password”
1.2 用户的创建、删除、授权与撤权
Mysql安装好后,默认有两个数据库(mysql和test),并且除了root用户外。其它用户仅仅能訪问test数据库。
Mysql中设置了5个授权表(user/db/host/tables_priv/columnts_priv)。
1) 创建新用户,方法例如以下:
A. mysql–u root –p #以管理员身份登录
B. insert into mysql.user(host,user,password) values(‘%’,’guest’,password(‘guest’));#创建一个username为guest的用户
C. flush privileges;#重载授权表
2) 删除用户,方法例如以下:
A. mysql–u root –p #以管理员身份登录
B. delete from mysql.user where user=’guest’;
C. flush privileges;
3) 更改用户password,方法例如以下:
A. mysql–u root –p #以管理员身份登录
B. update mysql.user set password=password(‘123’) where user=’guest’;
C. flush privileges;
4) 用户授权。方法例如以下:
格式:GRANT 权限列表[(字段列表)] ON 数据库名称.表名 TO username@域名或IP地址 [IDENTIFIED BY ‘password值’] [WITH GRANT OPTION];
经常使用权限例如以下:
全局管理权限: FILE: 在MySQLserver上读写文件。 PROCESS: 显示或杀死属于其他用户的服务线程。 RELOAD: 重载訪问控制表。刷新日志等。 SHUTDOWN: 关闭MySQL服务。 数据库/数据表/数据列权限: Alter: 改动已存在的数据表(比如添加/删除列)和索引。 Create: 建立新的数据库或数据表。 Delete: 删除表的记录。 Drop: 删除数据表或数据库。 INDEX: 建立或删除索引。 Insert: 添加表的记录。 Select: 显示/搜索表的记录。 Update: 改动表中已存在的记录。 特别的权限: ALL: 同意做不论什么事(和root一样)。 USAGE: 仅仅同意登录--其他什么也不同意做。 |
例一:要授权给用户guest能够从随意主机连接到数据库server,并具有全然訪问学生选课数据库xsxk的权限。
grant all on xsxk.* to guest@’%’ identified by ‘guest’;
说明:
A. %表示从不论什么主机连接到数据库server,也能够用空白
B. %.gdvcp.net 表示从gdvcp.net域中的不论什么主机连接到数据库server
C. 192.168.85.% 表示从192.168.85.0子网中不论什么主机连接到数据库server
D. localhost 表示从本地主机连接
E. 192.168.85.242 表示从IP为192.168.85.242的主机连接
例二:新建一个用户tom,让他能从子网192.168.85.0中不论什么主机连接到数据库server,能够读取数据库xsxk的内容。而且能改动表course中字段teacher的值。
grant select on xsxk.* to ’ identified by ‘123’;
grant update(teacher) on xsxk.course to ’;
例三:mysql管理员要授权用户admin能够从本地连接到数据库server,对学生选课数据库xsxk具有全然訪问权限,并可将其拥有的权限授予其它用户
grant all on xsxk.* to admin@localhost identified by ‘123’ with grant option;
5) 用户撤权。方法例如以下:
格式:REVOKE 权限列表[(字段列表)] ON 数据库名.表名 FROM username@域名或IP地址;
例:mysql管理员要撤销用户admin@localhost对数据库xsxk所拥有的创建删除数据库与表的权限,并撤销该用户能够把自己拥有的权限授予其它用户的权限。
revokecreate,drop on xsxk.* from admin@localhost;
revoke grant option on xsxk.* from admin@localhost;
1.3 数据库的创建与删除
1) 创建数据库:create database 数据库名;
2) 查看数据库:show databases;
3) 选择数据库:use 数据库名;
4) 删除数据库:drop database 数据库名;
1.4 表操作
1.4.1 基本操作
1) 创建表
格式:create table 表名(字段1,…字段n,[表级约束]) [Type=表类型];
注:
A. 字段i(i=1,…n)格式为:
字段名 字段类型 [字段约束]
说明一:字段类型。规定了某字段所同意输入的数据类型
类型 | 描写叙述 |
int | 同意值在0至2的32次方减1(无符号)之间标准整数 |
double | 双精度浮点数 |
char | 最大长度不超过255字符定长字符串 |
varchar | 最大长度不超过255字符变长字符串 |
text | 最大长度为65535字符字符串 |
blob | 可变数据的二进制类型 |
date | YYYYMMDD格式日期类型 |
说明二:字段约束,用来进一步对某个字段所同意输入的数据进行约束,经常使用的字段约束例如以下:
约束 | 描写叙述 |
NULL(或NOT NULL) | 指定同意(或不同意)某字段为空。默觉得NULL |
DEFAULT | 为某字段指定一个默认值 |
AUTO_INCREMENT | 自己主动为某个INT字段生成一个递增1的整数 |
B. 表级约束:用于表示表的主键、外键、索引和唯一约束。
约束 | 描写叙述 |
Primary key | 为表指定主键 |
Foreign key ……References | 为表指定外键 |
Unique | 为某字段创建索引。此字段必须唯一 |
Fulltext | 为某字段建立全文索引 |
C. 表类型:用于指定表的类型,即数据的存储格式。
表类型 | 描写叙述 |
MyISAM | 具有非常多优化和增强的特性。是mysql默认表类型 |
ISAM | 类似于MyISAM。但功能较少 |
HEAP | 保存在内存中。存取速度快,但存储容量小。恢复难 |
BDB | 支持事务和页锁定 |
INNODB | 支持事务、外键和行级锁。是mysql中最完好表格式 |
MERGE | 可把多个MyISAM表构建为一个虚拟表,使得这些表的查询就像在一个表上进行。提高查询速度和修复效率,并节省了磁盘空间 |
例:create table student(snovarchar(7) not null, snamevarchar(20) not null, ssex char(1) default ‘t’, sbirthday date, sdepa char(20), primary key(sno));
注:
a) 建好后可通过describe命令查看表结构
b) 系统会在/var/lib(or lib64)/mysql/xxkk文件夹下创建student.frm(表定义文件)、student.MDY(数据文件)、student.MYI(索引文件)三个文件
2) 复制表
格式:create table 新表名 like 源表名;
3) 删除表
格式:drop table 表名1[,表名2,…];
4) 改动表
格式:alter table 表名 更修改作1[,更修改作2,…];
A. 添加表中字段
alter table student add saddressvarchar(25);
B. 更改表字段名和字段类型
alter table student change saddressbeizhu text;
C. 删除字段
alter table student drop beizhu;
D. 更改名称
alter table student rename to xs;
1.4.2 表记录操作
1) 插入记录
格式:insert into 表名(字段1,字段2,…,字段n) values(字段1的值,字段2的值,…,字段n的值);
例1:要在表student中插入一组数据
insert into student(sno,sname,ssex,sbirthday,sdepa) values(‘1’,’lilei’,default,19850721,’math’);
例2:要插入与前一次操作同样的记录。可使用例如以下的缩写
insert into student values(‘1’,’lilei’,default,19850721,’math’);
例3:表中有默认字段。若取默认字段值,这时仅仅需改动要改动的内容
insert into student(sno,sname,sbirthday) values(‘2’,’lucy’,19850613);
例4:在一个insert语句中使用多个values字句,可插入多条记录
insert into student values(‘3’,’hanmeimei’,’f’,19850203,’computer’),(‘4’,’lily’,f,19850613,’computer’);
2) 删除记录
格式:delete from 表名 where 条件表达式
例1:删除表student中sno为’3’的记录
delete from student where sno=’3’;
例2:从表student中删除sname字段值前2位为’li’的记录
delete from student where left(sname,2)=’li’;
删除表中全部记录的方法:truncate table student;
3) 改动记录
格式:update 表名 set 字段名1=字段值1[,字段名2=字段值2,…] where 条件表达式;
例:改动表student中sno为’1’的记录,将其sdepa字段值改为’computer’
update student set sdepa=’computer’ where sno=’1’;
1.4.3 索引的创建与删除
1) 在创建表的同一时候创建索引
例:要创建一个选课课程表course。将课程编号cno设置为主键,同一时候为课程名称cname创建名为cna的索引
create table course(cnovarchar(5) not null, cnamevarchar(30) not null, teacher varchar(20), primary key(cno), index can(cname));
2) 向已存在的表加入索引(unique或index子句)
格式:create [unique] index 索引名 on 表名(字段名1[(长度)],…);
例1:为表student的sname创建名为sna的索引
create index sna on student(sname);
例2:为表student的sname创建名为sna的索引,且索引长度为10
create index sna on student(sname(10));
3) 删除索引
格式:drop index 索引名 on 表名;
例:删除表student中索引名为sna的索引
drop index sna on student;
2. Mysql查询
Mysql的查询语句和SQL Server基本同样,不同之处包含下面几点:
1) 获取前n个记录:SQL Server使用top n,位于select之后。mysql使用limit n,位于整个查询语句之后
3. Mysql存储过程
存储过程是数据库存储的一个重要的功能,可是MySQL在5.0曾经并不支持存储过程。
3.1 存储过程定义
3.1.1 格式
CREATE PROCEDURE过程名([过程參数[,...]])
[特性...]过程体样例:
mysql> DELIMITER // mysql> CREATE PROCEDURE proc1(OUT s int) -> BEGIN -> SELECT COUNT(*) INTO s FROM user; -> END -> // mysql> DELIMITER ; |
注:
A. 这里须要注意的是DELIMITER //和DELIMITER ;两句。DELIMITER是切割符的意思,由于MySQL默认以";"为分隔符。假设我们没有声明切割符,那么编译器会把存储过程当成SQL语句进行处理。则存储过程的编译过程会报错,所以要事先用DELIMITERkeyword申明当前段分隔符。这样MySQL才会将";"当做存储过程中的代码,不会运行这些代码,用完了之后要把分隔符还原。
B. 存储过程依据须要可能会有输入、输出、输入输出參数,这里有一个输出參数s,类型是int型,假设有多个參数用","切割开。
C. 假设过程体为多行。则它的開始与结束使用BEGIN与END进行标识。
3.1.2 切割符
假设是用MySQL的Administrator管理工具时。能够直接创建,不再须要声明切割符。
3.1.3 參数
MySQL存储过程的參数用在存储过程的定义,共同拥有三种參数类型,IN,OUT,INOUT,形式如:
CREATE PROCEDURE([[IN |OUT |INOUT ]參数名数据类形...])
IN输入參数:表示该參数的值必须在调用存储过程时指定,在存储过程中改动该參数的值不能被返回,为默认值
OUT输出參数:该值可在存储过程内部被改变。并可返回
INOUT输入输出參数:调用时指定,而且可被改变和返回
1) IN參数样例
创建:
1. mysql > DELIMITER // 2. mysql > CREATE PROCEDURE demo_in_parameter(IN p_in int) 3. -> BEGIN 4. -> SELECT p_in; 5. -> SET p_in=2; 6. -> SELECT p_in; 7. -> END; 8. -> // 9. mysql > DELIMITER ; |
运行结果:
1. mysql > SET @p_in=1; 2. mysql > CALL demo_in_parameter(@p_in); 3. +------+ 4. | p_in | 5. +------+ 6. | 1 | 7. +------+ 8. 9. +------+ 10. | p_in | 11. +------+ 12. | 2 | 13. +------+ 14. 15. mysql> SELECT @p_in; 16. +-------+ 17. | @p_in | 18. +-------+ 19. | 1 | 20. +-------+ |
以上能够看出。p_in尽管在存储过程中被改动,但并不影响@p_id的值
2) OUT參数样例
创建:
1. mysql > DELIMITER // 2. mysql > CREATE PROCEDURE demo_out_parameter(OUT p_out int) 3. -> BEGIN 4. -> SELECT p_out; 5. -> SET p_out=2; 6. -> SELECT p_out; 7. -> END; 8. -> // 9. mysql > DELIMITER ; |
运行结果:
1. mysql > SET @p_out=1; 2. mysql > CALL sp_demo_out_parameter(@p_out); 3. +-------+ 4. | p_out | 5. +-------+ 6. | NULL | 7. +-------+ 8. 9. +-------+ 10. | p_out | 11. +-------+ 12. | 2 | 13. +-------+ 14. 15. mysql> SELECT @p_out; 16. +-------+ 17. | p_out | 18. +-------+ 19. | 2 | 20. +-------+ |
3) INOUT參数样例
创建:
1. mysql > DELIMITER // 2. mysql > CREATE PROCEDURE demo_inout_parameter(INOUT p_inout int) 3. -> BEGIN 4. -> SELECT p_inout; 5. -> SET p_inout=2; 6. -> SELECT p_inout; 7. -> END; 8. -> // 9. mysql > DELIMITER ; |
运行结果:
1. mysql > SET @p_inout=1; 2. mysql > CALL demo_inout_parameter(@p_inout) ; 3. +---------+ 4. | p_inout | 5. +---------+ 6. | 1 | 7. +---------+ 8. 9. +---------+ 10. | p_inout | 11. +---------+ 12. | 2 | 13. +---------+ 14. 15. mysql > SELECT @p_inout; 16. +----------+ 17. | @p_inout | 18. +----------+ 19. | 2 | 20. +----------+ |
3.1.4 变量
1) 变量定义
DECLARE variable_name [,variable_name...] datatype [DEFAULT value];
当中,datatype为MySQL的数据类型。如:int, float, date, varchar(length)
比如:
1. DECLARE l_int int unsigned default 4000000;
2. DECLARE l_numeric number(8,2) DEFAULT 9.95;
3. DECLARE l_date date DEFAULT '1999-12-31';
4. DECLARE l_datetime datetime DEFAULT '1999-12-31 23:59:59';
5. DECLARE l_varchar varchar(255) DEFAULT 'This will not be padded';
2) 变量赋值
SET变量名=表达式值[,variable_name = expression ...]
3) 用户变量
A. 在MySQLclient使用用户变量
1. mysql > SELECT 'Hello World' into @x; 2. mysql > SELECT @x; 3. +-------------+ 4. | @x | 5. +-------------+ 6. | Hello World | 7. +-------------+ 8. mysql > SET @y='Goodbye Cruel World'; 9. mysql > SELECT @y; 10. +---------------------+ 11. | @y | 12. +---------------------+ 13. | Goodbye Cruel World | 14. +---------------------+ 15. 16. mysql > SET @z=1+2+3; 17. mysql > SELECT @z; 18. +------+ 19. | @z | 20. +------+ 21. | 6 | 22. +------+ |
B. 在存储过程中使用用户变量
1. mysql > CREATE PROCEDURE GreetWorld( ) SELECT CONCAT(@greeting,' World'); 2. mysql > SET @greeting='Hello'; 3. mysql > CALL GreetWorld( ); 4. +----------------------------+ 5. | CONCAT(@greeting,' World') | 6. +----------------------------+ 7. | Hello World | 8. +----------------------------+ |
C. 在存储过程间传递全局范围的用户变量
1. mysql> CREATE PROCEDURE p1() SET @last_procedure='p1'; 2. mysql> CREATE PROCEDURE p2() SELECT CONCAT('Last procedure was ',@last_proc); 3. mysql> CALL p1( ); 4. mysql> CALL p2( ); 5. +-----------------------------------------------+ 6. | CONCAT('Last procedure was ',@last_proc | 7. +-----------------------------------------------+ 8. | Last procedure was p1 | 9. +-----------------------------------------------+ |
注意:
a) 户变量名一般以@开头
b) 滥用用户变量会导致程序难以理解及管理
3.1.5 凝视
MySQL存储过程可使用两种风格的凝视
双模杠:--一般用于单行凝视
c风格:一般用于多行凝视
比如:
1. mysql > DELIMITER // 2. mysql > CREATE PROCEDURE proc1 --name存储过程名 3. -> (IN parameter1 INTEGER) 4. -> BEGIN 5. -> DECLARE variable1 CHAR(10); 6. -> IF parameter1 = 17 THEN 7. -> SET variable1 = 'birds'; 8. -> ELSE 9. -> SET variable1 = 'beasts'; 10. -> END IF; 11. -> INSERT INTO table1 VALUES (variable1); 12. -> END 13. -> // 14. mysql > DELIMITER ; |
3.2 存储过程特点
1) MySQL 存储过程名字后面的“()”是必须的,即使没有一个參数,也须要“()”
2) MySQL 存储过程參数,不能在參数名称前加“@”,如:“@a int”。
以下的创建存储过程语法在 MySQL 中是错误的(在 SQL Server 中是正确的)。 MySQL 存储过程中的变量,不须要在变量名字前加“@”,尽管 MySQL client用户变量要加个“@”。
create procedure pr_add ( @a int, -- 错误 b int -- 正确 ) |
3) MySQL 存储过程的參数不能指定默认值。
4) MySQL 存储过程不须要在 procedure body 前面加 “as”。而 SQL Server 存储过程必须加 “as” keyword。
create procedure pr_add ( a int, b int ) as -- 错误,MySQL 不须要 “as” begin mysql statement ...; end; |
5) 假设 MySQL 存储过程中包括多条 MySQL 语句,则须要 begin end keyword。
6) MySQL 存储过程中的每条语句的末尾,都要加上分号 “;”
7) 不能在 MySQL 存储过程中使用 “return” keyword。
8) 由于 MySQL 存储过程參数没有默认值。所以在调用 MySQL 存储过程时候,不能省略參数。能够用 null 来替代
3.3 存储过程调用
用call和你过程名以及一个括号,括号中面依据须要。增加參数。參数包含输入參数、输出參数、输入输出參数。详细的调用方法能够參看上面的样例。
3.4 存储过程查询
我们像知道一个数据库以下有那些表,我们一般採用show tables;进行查看。
那么我们要查看某个数据库以下的存储过程,是否也能够採用呢?答案是,我们能够查看某个数据库以下的存储过程,可是是令一钟方式。
我们能够用
select name from mysql.proc where db=’数据库名’;
或者
select routine_name from information_schema.routines where routine_schema='数据库名';
或者
show procedure status where db='数据库名';
进行查询。
假设我们想知道。某个存储过程的具体。那我们又该怎么做呢?是不是也能够像操作表一样用describe表名进行查看呢?
答案是:我们能够查看存储过程的具体,可是须要用还有一种方法:
SHOW CREATE PROCEDURE数据库.存储过程名;
就能够查看当前存储过程的具体。
3.5 存储过程改动
ALTER PROCEDURE
更改用CREATE PROCEDURE建立的预先指定的存储过程。其不会影响相关存储过程或存储功能。
3.6 存储过程删除
DROP PROCEDURE
从MySQL的表格中删除一个或多个存储过程。
3.7 存储过程控制语句
变量作用域
内部的变量在其作用域范围内享有更高的优先权,当运行到end。
变量时。内部变量消失。此时已经在其作用域外,变量不再可见了,应为在存储
过程外再也不能找到这个申明的变量,可是你能够通过out參数或者将其值指派 给会话变量来保存其值。 1. mysql > DELIMITER // 2. mysql > CREATE PROCEDURE proc3() 3. -> begin 4. -> declare x1 varchar(5) default 'outer'; 5. -> begin 6. -> declare x1 varchar(5) default 'inner'; 7. -> select x1; 8. -> end; 9. -> select x1; 10. -> end; 11. -> // 12. mysql > DELIMITER ; |
条件语句
1) if-then -else语句
1. mysql > DELIMITER // 2. mysql > CREATE PROCEDURE proc2(IN parameter int) 3. -> begin 4. -> declare var int; 5. -> set var=parameter+1; 6. -> if var=0 then 7. -> insert into t values(17); 8. -> end if; 9. -> if parameter=0 then 10. -> update t set s1=s1+1; 11. -> else 12. -> update t set s1=s1+2; 13. -> end if; 14. -> end; 15. -> // 16. mysql > DELIMITER ; |
2) case语句:
1. mysql > DELIMITER // 2. mysql > CREATE PROCEDURE proc3 (in parameter int) 3. -> begin 4. -> declare var int; 5. -> set var=parameter+1; 6. -> case var 7. -> when 0 then 8. -> insert into t values(17); 9. -> when 1 then 10. -> insert into t values(18); 11. -> else 12. -> insert into t values(19); 13. -> end case; 14. -> end; 15. -> // 16. mysql > DELIMITER ; |
3) 循环语句
A. while ···· end while:
1. mysql > DELIMITER // 2. mysql > CREATE PROCEDURE proc4() 3. -> begin 4. -> declare var int; 5. -> set var=0; 6. -> while var<6 do 7. -> insert into t values(var); 8. -> set var=var+1; 9. -> end while; 10. -> end; 11. -> // 12. mysql > DELIMITER ; |
B. repeat···· end repeat:
1. mysql > DELIMITER // 2. mysql > CREATE PROCEDURE proc5 () 3. -> begin 4. -> declare v int; 5. -> set v=0; 6. -> repeat 7. -> insert into t values(v); 8. -> set v=v+1; 9. -> until v>=5 10. -> end repeat; 11. -> end; 12. -> // 13. mysql > DELIMITER ; |
C. loop ·····end loop:
loop循环不须要初始条件,这点和while循环相似,同一时候和repeat循环一样不须要结束条件, leave语句的意义是离开循环。
1. mysql > DELIMITER // 2. mysql > CREATE PROCEDURE proc6 () 3. -> begin 4. -> declare v int; 5. -> set v=0; 6. -> LOOP_LABLE:loop 7. -> insert into t values(v); 8. -> set v=v+1; 9. -> if v >=5 then 10. -> leave LOOP_LABLE; 11. -> end if; 12. -> end loop; 13. -> end; 14. -> // 15. mysql > DELIMITER ; |
D. LABLES标号:
标号能够用在begin repeat while或者loop语句前,语句标号仅仅能在合法的语句前面使用。能够跳出循环,使执行指令达到复合语句的最后一步。
4) ITERATE迭代
通过引用复合语句的标号,来从新開始复合语句
1. mysql > DELIMITER // 2. mysql > CREATE PROCEDURE proc10 () 3. -> begin 4. -> declare v int; 5. -> set v=0; 6. -> LOOP_LABLE:loop 7. -> if v=3 then 8. -> set v=v+1; 9. -> ITERATE LOOP_LABLE; 10. -> end if; 11. -> insert into t values(v); 12. -> set v=v+1; 13. -> if v>=5 then 14. -> leave LOOP_LABLE; 15. -> end if; 16. -> end loop; 17. -> end; 18. -> // 19. mysql > DELIMITER ; |
3.8 存储过程基本函数
字符串类
1) CHARSET(str) //返回字串字符集
2) CONCAT (string2 [,... ]) //连接字串
3) INSTR (string ,substring ) //返回substring首次在string中出现的位置,不存在返回0
4) LCASE (string2 ) //转换成小写
5) LEFT (string2 ,length ) //从string2中的左边起取length个字符
6) LENGTH (string ) //string长度
7) LOAD_FILE (file_name ) //从文件读取内容
8) LOCATE (substring , string [,start_position ] )同INSTR,但可指定開始位置
9) LPAD (string2 ,length ,pad ) //反复用pad加在string开头,直到字串长度为length
10) LTRIM (string2 ) //去除前端空格
11) REPEAT (string2 ,count ) //反复count次
12) REPLACE (str ,search_str ,replace_str ) //在str中用replace_str替换search_str
13) RPAD (string2 ,length ,pad) //在str后用pad补充,直到长度为length
14) RTRIM (string2 ) //去除后端空格
15) STRCMP (string1 ,string2 ) //逐字符比較两字串大小,
16) SUBSTRING (str , position [,length ]) //从str的position開始,取length个字符
注:mysql中处理字符串时,默认第一个字符下标为1,即參数position必须大于等于1
例:
1. mysql> select substring('abcd',0,2); 2. +-----------------------+ 3. | substring('abcd',0,2) | 4. +-----------------------+ 5. | | 6. +-----------------------+ 7. 1 row in set (0.00 sec) 8. 9. mysql> select substring('abcd',1,2); 10. +-----------------------+ 11. | substring('abcd',1,2) | 12. +-----------------------+ 13. | ab | 14. +-----------------------+ 15. 1 row in set (0.02 sec) |
17) TRIM([[BOTH|LEADING|TRAILING] [padding] FROM]string2) //去除指定位置的指定字符
18) UCASE (string2 ) //转换成大写
19) RIGHT(string2,length) //取string2最后length个字符
20) SPACE(count) //生成count个空格
数学类
1) ABS (number2 ) //绝对值
2) BIN (decimal_number ) //十进制转二进制
3) CEILING (number2 ) //向上取整
4) CONV(number2,from_base,to_base) //进制转换
5) FLOOR (number2 ) //向下取整
6) FORMAT (number,decimal_places ) //保留小数位数
7) HEX (DecimalNumber ) //转十六进制
注:HEX()中可传入字符串。则返回其ASC-11码,如HEX('DEF')返回4142143
也能够传入十进制整数,返回其十六进制编码,如HEX(25)返回198) LEAST (number , number2 [,..]) //求最小值
9) MOD (numerator ,denominator ) //求余
10) POWER (number ,power ) //求指数
11) RAND([seed]) //随机数
12) ROUND (number [,decimals ]) //四舍五入,decimals为小数位数]
注:返回类型并不是均为整数,如:
(1)默认变为整形值 1. mysql> select round(1.23); 2. +-------------+ 3. | round(1.23) | 4. +-------------+ 5. | 1 | 6. +-------------+ 7. 1 row in set (0.00 sec) 8. 9. mysql> select round(1.56); 10. +-------------+ 11. | round(1.56) | 12. +-------------+ 13. | 2 | 14. +-------------+ 15. 1 row in set (0.00 sec) |
(2)能够设定小数位数。返回浮点型数据
1. mysql> select round(1.567,2); 2. +----------------+ 3. | round(1.567,2) | 4. +----------------+ 5. | 1.57 | 6. +----------------+ 7. 1 row in set (0.00 sec) 8. SIGN (number2 ) // |
日期时间类
1) ADDTIME (date2 ,time_interval ) //将time_interval加到date2
2) CONVERT_TZ (datetime2 ,fromTZ ,toTZ ) //转换时区
3) CURRENT_DATE ( ) //当前日期
4) CURRENT_TIME ( ) //当前时间
5) CURRENT_TIMESTAMP ( ) //当前时间戳
6) DATE (datetime ) //返回datetime的日期部分
7) DATE_ADD (date2 , INTERVAL d_valued_type ) //在date2中加上日期或时间
8) DATE_FORMAT (datetime ,FormatCodes ) //使用formatcodes格式显示datetime
9) DATE_SUB (date2 , INTERVAL d_valued_type ) //在date2上减去一个时间
10) DATEDIFF (date1 ,date2 ) //两个日期差
11) DAY (date ) //返回日期的天
12) DAYNAME (date ) //英文星期
13) DAYOFWEEK (date ) //星期(1-7) ,1为星期天
14) DAYOFYEAR (date ) //一年中的第几天
15) EXTRACT (interval_name FROM date ) //从date中提取日期的指定部分
16) MAKEDATE (year ,day ) //给出年及年中的第几天,生成日期串
17) MAKETIME (hour ,minute ,second ) //生成时间串
18) MONTHNAME (date ) //英文月份名
19) NOW ( ) //当前时间
20) SEC_TO_TIME (seconds ) //秒数转成时间
21) STR_TO_DATE (string ,format ) //字串转成时间,以format格式显示
22) TIMEDIFF (datetime1 ,datetime2 ) //两个时间差
23) TIME_TO_SEC (time ) //时间转秒数]
24) WEEK (date_time [,start_of_week ]) //第几周
25) YEAR (datetime ) //年份
26) DAYOFMONTH(datetime) //月的第几天
27) HOUR(datetime) //小时
28) LAST_DAY(date) //date的月的最后日期
29) MICROSECOND(datetime) //微秒
30) MONTH(datetime) //月
31) MINUTE(datetime) //分返回符号,正负或0
32) SQRT(number2) //开平方
3.9 事务、游标的使用
事务
-- 启动事务 start transaction; …… -- 执行没有异常。提交事务 commit; |
游标
-- 声明游标 declare cur cursor for
-- 声明游标的异常处理,设置一个终止标记 declare CONTINUE HANDLER FOR SQLSTATE '02000' SET stop=1;
-- 打开游标 open cur;
-- 读取一行数据到变量 fetch cur into
-- 这个就是推断是否游标已经到达了最后 while stop <> 1 do
-- 读取下一行的数据 fetch cur int
-- 关闭游标 close cur; |
4. Mysql视图
4.1 创建视图
4.1.1 定义
格式:create [or replace] [algorithm = {undefined | merge | temptable}] view [db_name.]view_name [(column_list)] as select_statement [with [cascaded | local] check option]
注:
A. 若给定了[or replace]。则表示当已具有同名的视图时,将覆盖原视图。
B. select_statement是一个查询语句,这个查询语句可从表或其他的视图中查询。
C. 视图属于数据库,因此须要指定数据库的名称。若未指定时,表示在当前的数据库创建新视图。
D. 表和表共享数据库中同样的名称空间,因此,数据库不能包括同样名称的表和视图。而且。视图的列名也不能反复。
4.1.2 举例
创建一个产品表(product)和一个购买记录表(purchase),再通过视图purchase_detail查询出购买的具体信息。
create table product ( product_idint not null, name varchar(50) not null, price double not null ); insert into product values(1, 'apple ', 5.5); create table purchase ( id int not null, product_idint not null, qtyint not null default 0, gen_timedatetime not null ); insert into purchase values(1, 1, 10, now()); create view purchase_detail as select product.name as name, product .price as price, purchase.qty as qty, product .price * purchase.qty as total_value from product, purchase where product.product_id = purchase.product_id; |
创建成功后,输入:select * from purchase_detail;
执行效果例如以下:
+-------+-------+-----+-------------+ | name | price | qty | total_value | +-------+-------+-----+-------------+ | apple | 5.5 | 10 | 55 | +-------+-------+-----+-------------+ 1 row in set (0.01 sec) |
4.1.3 注意事项
1) 执行创建视图的语句须要用户具有创建视图(crate view)的权限,若加了[or replace]时。还须要用户具有删除视图(drop view)的权限。
2) select语句不能包括from子句中的子查询;
3) select语句不能引用系统或用户变量。
4) select语句不能引用预处理语句參数;
5) 在存储子程序内,定义不能引用子程序參数或局部变量;
6) 在定义中引用的表或视图必须存在。
可是。创建了视图后,可以舍弃定义引用的表或视图。要想检查视图定义是否存在这类问题。可使用check table语句;
7) 在定义中不能引用temporary表。不能创建temporary视图;
8) 在视图定义中命名的表必须已存在;
9) 不能将触发程序与视图关联在一起;
10) 在视图定义中同意使用order by,可是,假设从特定视图进行了选择。而该视图使用了具有自己order by的语句,它将被忽略。
4.2 改动视图
4.2.1 定义
格式:alter [algorithm = {undefined | merge | temptable}] view view_name [(column_list)] as select_statement [with [cascaded | local] check option]
4.2.2 举例
将上一小节中中创建的视purchase_detail进行改动,去掉qty列,语句例如以下:
alter view purchase_detail as select product.name as name, product .price as price, product .price * purchase.qty as total_value from product, purchase where product.product_id = purchase.product_id; |
5. Mysql作业
MySQL的事件调度器能够精确到每秒钟运行一个任务。而操作系统的计划任务(如:Linux下的CRON或Windows下的任务计划)仅仅能精确到每分钟运行一次。
事件调度器有时也可称为暂时触发器(temporal triggers),由于事件调度器是基于特定时间周期触发来运行某些任务,而触发器(Triggers)是基于某个表所产生的事件触发的。差别也就在这里。
5.1. 开启事件调度器
5.1.1. 开启
有例如以下几种方法:
1) 运行:SET GLOBAL event_scheduler = 1
2) 运行:SET GLOBAL event_scheduler = ON
3) 在配置my.cnf文件 中加上 event_scheduler = 1
4) 在启动命令加上”--event_scheduler=1”
5.1.2. 查看
有例如以下方法:
1) 运行:SHOW VARIABLES LIKE “event_scheduler”
2) 运行:select @event_scheduler
3) 运行:SHOW PROCESSLIST
5.2. 创建事件(CREATE EVENT)
5.2.1. 语法
CREATE EVENT [IF NOT EXISTS] event_name ON SCHEDULE schedule [ON COMPLETION [NOT] PRESERVE] [ENABLE | DISABLE] [COMMENT 'comment'] DO sql_statement; |
5.2.2. 參数
1) schedule:
AT TIMESTAMP [+ INTERVAL INTERVAL]
| EVERY INTERVAL [STARTS TIMESTAMP] [ENDS TIMESTAMP]
2) INTERVAL:
quantity {YEAR | QUARTER | MONTH | DAY | HOUR | MINUTE |
WEEK | SECOND | YEAR_MONTH | DAY_HOUR | DAY_MINUTE |
DAY_SECOND | HOUR_MINUTE | HOUR_SECOND | MINUTE_SECOND}
5.2.3. 举例
先创建一个表
CREATE TABLE aaa (timeline TIMESTAMP); |
1) 每秒插入一条记录到数据表
CREATE EVENT e_test_insert ON SCHEDULE EVERY 1 SECOND DO INSERT INTO aaa VALUES (CURRENT_TIMESTAMP); |
2) 5天后清空aaa表
CREATE EVENT e_test ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 5 DAY DO TRUNCATE TABLE aaa; |
3) 每天定时清空aaa表:
CREATE EVENT e_test ON SCHEDULE EVERY 1 DAY DO TRUNCATE TABLE aaa; |
4) 5天后开启每天定时清空aaa表:
CREATE EVENT e_test ON SCHEDULE EVERY 1 DAY STARTS CURRENT_TIMESTAMP + INTERVAL 5 DAY DO TRUNCATE TABLE aaa; |
5) 每天定时清空aaa表。5天后停止运行:
CREATE EVENT e_test ON SCHEDULE EVERY 1 DAY ENDS CURRENT_TIMESTAMP + INTERVAL 5 DAY DO TRUNCATE TABLE aaa; |
6) 5天后开启每天定时清空test表,一个月后停止运行:
CREATE EVENT e_test ON SCHEDULE EVERY 1 DAY STARTS CURRENT_TIMESTAMP + INTERVAL 5 DAY ENDS CURRENT_TIMESTAMP + INTERVAL 1 MONTH DO TRUNCATE TABLE aaa; |
7) 每天定时清空test表(仅仅运行一次,任务完毕后就终止该事件):
[ON COMPLETION [NOT] PRESERVE]能够设置这个事件是运行一次还是持久运行。默觉得NOT PRESERVE。[ENABLE | DISABLE]但是设置该事件创建后状态是否开启或关闭。默觉得ENABLE。
[COMMENT ‘comment’]能够给该事件加上凝视。
CREATE EVENT e_test ON SCHEDULE EVERY 1 DAY ON COMPLETION NOT PRESERVE DO TRUNCATE TABLE aaa; |
5.3. 改动事件(ALTER EVENT)
5.3.1. 语法
ALTER EVENT event_name [ON SCHEDULE schedule] [RENAME TO new_event_name] [ON COMPLETION [NOT] PRESERVE] [COMMENT 'comment'] [ENABLE | DISABLE] [DO sql_statement] |
5.3.2. 举例
1) 暂时关闭事件:ALTER EVENT e_test DISABLE | OFF
2) 开启事件:ALTER EVENT e_test ENABLE | ON
3) 将每天清空aaa表改为5天清空一次:
ALTER EVENT e_test ON SCHEDULE EVERY 5 DAY; |
5.4. 删除事件(DROP EVENT)
5.4.1. 语法
DROP EVENT [IF EXISTS] event_name |
5.4.2. 注意事项
1) 删除事件的前提是事件必须存在。否则会产生ERROR 1513(HY000):Unknown event错误,因此最好加上IF EXISTS
2) 删除事件时假设事件状态为DISABLE,则当又一次启动mysql服务后,该事件将被删除
6. Mysql Prepare
当用变量做表名时,简单的用set或者declare语句定义变量。然后直接作为sql的表名是不行的。mysql会把变量名当作表名。在其它的sql数据库中也是如此。mssql使用例如以下的语句解决:
PREPARE stmt_name FROM preparable_stmt; EXECUTE stmt_name [USING @var_name [, @var_name] ...]; {DEALLOCATE | DROP} PREPARE stmt_name; |
注:
A. PREPARE stmt_name FROM preparable_stmt;提前定义一个语句,并将它赋给stmt_name。tmt_name是不区分大写和小写的。
B. 即使preparable_stmt语句中的?所代表的是一个字符串,你也不须要将?用引號包括起来。
C. 假设新的 PREPARE 语句使用了一个已存在的stmt_name,那么原有的将被马上释放!
即使这个新的 PREPARE 语句由于错误而不能被正确运行。
D. PREPARE stmt_name的作用域是当前client连接会话可见。
E. 要释放一个提前定义语句的资源,能够使用 DEALLOCATE PREPARE 句法。
F. EXECUTE stmt_name句法中。假设stmt_name不存在,将会引发一个错误。
G. 假设在终止client连接会话时,没有显式地调用 DEALLOCATE PREPARE 句法释放资源,server端会自己动释放它。
H. 在提前定义语句中,CREATE TABLE, DELETE, DO, INSERT, REPLACE, SELECT, SET, UPDATE, 和大部分的 SHOW 句法被支持。
I. PREPARE 语句不能够用于自己定义函数。
触发器
样例1:创建两个表。目的是在一个表里加入一条记录,还有一个表也加入一条记录:
a.sql的内容
create database my_frist_db; use my_frist_db; DROP TABLE IF EXISTS tab1; CREATE TABLE tab1( tab1_id varchar(11) ); DROP TABLE IF EXISTS tab2; CREATE TABLE tab2( tab2_id varchar(11) ); delimiter || DROP TRIGGER IF EXISTS t_afterinsert_on_tab1 || CREATE TRIGGER t_afterinsert_on_tab1 AFTER INSERT ON tab1 FOR EACH ROW BEGIN insert into tab2(tab2_id) values(new.tab1_id); END|| delimiter ; INSERT INTO tab1(tab1_id) values('0001');运行结果
a@ubuntu:~/db$ mysql -h localhost -u root -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 50 Server version: 5.5.43-0ubuntu0.14.04.1 (Ubuntu) Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> source a.sql Query OK, 1 row affected (0.00 sec) Database changed Query OK, 0 rows affected, 1 warning (0.00 sec) Query OK, 0 rows affected (0.14 sec) Query OK, 0 rows affected, 1 warning (0.00 sec) Query OK, 0 rows affected (0.02 sec) Query OK, 0 rows affected, 1 warning (0.00 sec) Query OK, 0 rows affected (0.04 sec) Query OK, 1 row affected (0.17 sec) mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | my_frist_db | | mysql | | performance_schema | +--------------------+ 4 rows in set (0.02 sec) mysql> use my_frist_db Database changed mysql> show tables; +-----------------------+ | Tables_in_my_frist_db | +-----------------------+ | tab1 | | tab2 | +-----------------------+ 2 rows in set (0.03 sec) mysql> select * from tab1; +---------+ | tab1_id | +---------+ | 0001 | +---------+ 1 row in set (0.02 sec) mysql> select * from tab2; +---------+ | tab2_id | +---------+ | 0001 | +---------+ 1 row in set (0.00 sec) mysql> SHOW TRIGGERS\G; *************************** 1. row *************************** Trigger: t_afterinsert_on_tab1 Event: INSERT Table: tab1 Statement: BEGIN insert into tab2(tab2_id) values(new.tab1_id); END Timing: AFTER Created: NULL sql_mode: Definer: root@localhost character_set_client: utf8 collation_connection: utf8_general_ci Database Collation: latin1_swedish_ci 1 row in set (0.20 sec) ERROR: No query specified mysql>样例2:创建两个表。目的是在一个表里删除一条记录,还有一个表也删除一条记录:
trig.sql的内容
delimiter || DROP TRIGGER IF EXISTS t_afterdelete_on_tab1|| CREATE TRIGGER t_afterdelete_on_tab1 AFTER DELETE ON tab1 FOR EACH ROW BEGIN delete from tab2 where tab2_id=old.tab1_id; END|| DELETE FROM tab1 WHERE tab1_id='0001'; SELECT * FROM tab1; SELECT * FROM tab2;运行结果
mysql> source trig.sql
Query OK, 0 rows affected, 1 warning (0.00 sec) Query OK, 0 rows affected (0.04 sec) Query OK, 1 row affected (0.16 sec) Empty set (0.16 sec) Empty set (0.16 sec)样例3 udate触发器,一个表改动了同一时候改动另外一个表
trig.sql内容
CREATE DATABASE my_frist_db;
USE my_frist_db; DROP TABLE IF EXISTS tab1; CREATE TABLE tab1( tab_id varchar(11), provinceNameCn varchar(24) ); DROP TABLE IF EXISTS tab2; CREATE TABLE tab2( tab_id varchar(11), provinceNameCn varchar(24) ); delimiter || DROP TRIGGER IF EXISTS t_afterinsert_on_tab1 || CREATE TRIGGER t_afterinsert_on_tab1 AFTER INSERT ON tab1 FOR EACH ROW BEGIN insert into tab2(tab_id,provinceNameCn) values(new.tab_id,new.provinceNameCn); END|| delimiter ; delimiter || DROP TRIGGER IF EXISTS t_afterdelete_on_tab1|| CREATE TRIGGER t_afterdelete_on_tab1 AFTER DELETE ON tab1 FOR EACH ROW BEGIN delete from tab2 where tab_id=old.tab_id; END|| delimiter ; delimiter || DROP TRIGGER IF EXISTS t_afterupdate_on_tab1|| CREATE TRIGGER t_afterupdate_on_tab1 AFTER UPDATE ON tab1 FOR EACH ROW BEGIN update tab2 set provinceNameCn=new.provinceNameCn where tab_id=new.tab_id; #DELETE FROM tab2 WHERE tab_id='00'; #INSERT INTO tab2(tab_id,provinceNameCn) values(new.tab_id,new.provinceNameCn); END|| delimiter ; INSERT INTO tab1(tab_id,provinceNameCn) VALUES('0001','aaa'); INSERT INTO tab1(tab_id,provinceNameCn) VALUES('0002','aab'); INSERT INTO tab1(tab_id,provinceNameCn) VALUES('0003','aac'); SELECT * FROM tab1; SELECT * FROM tab2; UPDATE tab1 SET provinceNameCn='999' WHERE tab_id='0002'; SELECT * FROM tab1; SELECT * FROM tab2; DELETE FROM tab1 WHERE tab_id='0001'; SELECT * FROM tab1; SELECT * FROM tab2;运行结果
mysql> source trig.sql
ERROR 1007 (HY000): Can't create database 'my_frist_db'; database exists Database changed Query OK, 0 rows affected (0.00 sec) Query OK, 0 rows affected (0.04 sec) Query OK, 0 rows affected (0.02 sec) Query OK, 0 rows affected (0.00 sec) Query OK, 0 rows affected, 1 warning (0.00 sec) Query OK, 0 rows affected (0.00 sec) Query OK, 0 rows affected, 1 warning (0.00 sec) Query OK, 0 rows affected (0.00 sec) Query OK, 0 rows affected, 1 warning (0.01 sec) Query OK, 0 rows affected (0.00 sec) Query OK, 1 row affected (0.05 sec) Query OK, 1 row affected (0.00 sec) Query OK, 1 row affected (0.00 sec) +--------+----------------+ | tab_id | provinceNameCn | +--------+----------------+ | 0001 | aaa | | 0002 | aab | | 0003 | aac | +--------+----------------+ 3 rows in set (0.00 sec) +--------+----------------+ | tab_id | provinceNameCn | +--------+----------------+ | 0001 | aaa | | 0002 | aab | | 0003 | aac | +--------+----------------+ 3 rows in set (0.00 sec) Query OK, 1 row affected (0.10 sec) Rows matched: 1 Changed: 1 Warnings: 0 +--------+----------------+ | tab_id | provinceNameCn | +--------+----------------+ | 0001 | aaa | | 0002 | 999 | | 0003 | aac | +--------+----------------+ 3 rows in set (0.00 sec) +--------+----------------+ | tab_id | provinceNameCn | +--------+----------------+ | 0001 | aaa | | 0002 | 999 | | 0003 | aac | +--------+----------------+ 3 rows in set (0.00 sec) Query OK, 1 row affected (0.01 sec) +--------+----------------+ | tab_id | provinceNameCn | +--------+----------------+ | 0002 | 999 | | 0003 | aac | +--------+----------------+ 2 rows in set (0.00 sec) +--------+----------------+ | tab_id | provinceNameCn | +--------+----------------+ | 0002 | 999 | | 0003 | aac | +--------+----------------+ 2 rows in set (0.00 sec)下订单自己主动降低库存,更改订单的时候纠正库存,恶意订单时纠正数量
现有例如以下两张表
1)商品表(库存表)
编号(id)名称(name)价格(price)库存(stock)
1 F16战斗机 10000 100 2 法拉利 800 70 3 航空母舰 5000 20 4 三栖交通工具 1000 50DROP TABLE IF EXISTS shop;
CREATE TABLE shop( id int(11), name varchar(11), price int(11), stock int(11) );INSERT INTO shop(id,name,price,stock) values(1,'F16战斗机', 10000, 10);
INSERT INTO shop(id,name,price,stock) values(2,'法拉利', 800, 100); INSERT INTO shop(id,name,price,stock) values(3,'航空母舰',5000, 11); INSERT INTO shop(id,name,price,stock) values(4,'三栖交通工具', 1000, 30);2)订单表
编号(id)商品编号(tid)购买数量(num)
DROP TABLE IF EXISTS commande; CREATE TABLE commande( tid int(11), num int(11) );我们如今要买5架F16战斗机,下一个订单,须要做什么?
传统的做法:
insert into commande(tid,num) values(1,5); update shop set stock = stock-5 where id = 1;新的方式:
我们能够使用触发器,一触即发!!触发器四要素:
地点:(表,table),
监视的事件:(insert,delete,update) 时间:(before/after) 触发的事件:(insert,delete,update)需求:如今我们要购买10辆法拉利, 商品表里的触发器应该 这样写:
#商品表的触发器
delimiter || DROP TRIGGER IF EXISTS tg1_insert_shop || create trigger tg1_insert_shop after -- 事件触发在 下订单之后 insert -- 监视插入事件 on commande -- 监视 order订单表 for each row begin update shop set stock=stock-new.num where id= new.tid; -- 注意这里是 old.id=new.tid end || delimiter ;运行在commande表的操作:
insert into commande(tid,num) values(2,10);
需求:先购买了10个辆法拉利,然后要把数量更改为5。写出触发器;
#商品表的触发器
delimiter || DROP TRIGGER IF EXISTS tg1_update_shop || create trigger tg1_update_shop after update on commande for each row begin update shop set stock = stock + old.num - new.num where id = new.tid; -- 监视更新,既不漏掉旧的,也不漏掉新的,计算差额 end || delimiter ;測试:
update commande set num=8 where tid=2; 需求:若订单数量超过10的话。就觉得是恶意订单,仅仅让其购买10个。 Before:在监视事件发生之前触发的,触发事件要早于监视事件。#商品表的触发器
delimiter $ create trigger tg_update_before before insert on commande for each row begin if new.num > 10 then set new.num = 10; end if; update shop set stock = stock - new.num where id = new.tid; end $測试:
insert into commande(tid,num) values(2,22);
MySQL 触发器insert 演示样例一
- view sourceprint?
01 delimiter //
- create trigger InsertUser
- before insert on user
- for each row
- Begin
- insert into user_group(uid,gid) values(new.uid,'group4444444444');
- end;//
- delimiter ;
MySQL 触发器insert 演示样例二
- delimiter //
- create trigger InsertUser
- before insert on user
- for each row
- Begin
- IF new.Type=2 then
- insert into user_group(uid,gid) values(new.uid,'group4444444444');
- else
- insert into user_group(uid,gid) values(new.uid,'group55555555555')
- END IF;
- end;//
- delimiter ;
MySQL 触发器insert 演示样例三:
- delimiter //
- create trigger InsertUser
- before insert on user
- for each row
- Begin
- IF new.type=1 then
- insert into user_group(uid,gid) values(new.uid,'578d3369633b47bd9c1fe8bf905cbfb1');
- END IF;
- IF new.type=2 then
- insert into user_group(uid,gid) values(new.uid,'387bcd57fc5a4c3c9de83ee210fef661');
- END IF;
- end;//
- delimiter ;
mysql的 insert触发器。怎样更改插入后的值
触发器背景知识
创建触发器
创建仅仅有一个运行语句的触发器
BEFORE和AFTER參数指定了触发运行的时间。在事件之前或是之后
FOR EACH ROW表示不论什么一条记录上的操作满足触发事件都会触发该触发器
代码例如以下:
创建有多个运行语句的触发器
tips:普通情况下,mysql默认是以 ; 作为结束运行语句,与触发器中须要的分行起冲突
为解决此问题可用DELIMITER,如:DELIMITER ||,能够将结束符号变成||
当触发器创建完毕后,能够用DELIMITER ;来将结束符号变成;
mysql> DELIMITER ;
就会运行BEGIN和END中的语句。接着使用||结束
最后使用DELIMITER ; 将结束符号还原
查看触发器
SHOW TRIGGERS语句查看触发器信息
tips:SHOW TRIGGERS语句无法查询指定的触发器
在triggers表中查看触发器信息
代码例如以下:
能够使用SELECT语句查询,假设触发器信息过多。最好通过TRIGGER_NAME字段指定查询
删除触发器
同一时候,也能够使用database.trig来指定某个数据库中的触发器
tips:假设不须要某个触发器时一定要将这个触发器删除。以免造成意外操作