您的位置:首页 > 运维架构 > Linux

【Linux】 MySQL

2015-06-09 19:48 211 查看

安装

命令如下:

[code]$ sudo apt-get install mysql-server
$ sudo apt-get install mysql-client
$ sudo apt-get install libmysqlclient-dev


其中查看当前mysql是否开启:

[code]$ netstat -tap | grep mysql


开启mysql:

[code]$ mysql -u username -p 
Enter password:


编码

创建新用户:

[code]GRANT ALL ON *.* TO **LETENO** IDENTIFIED BY 'PASSWORD';
创建用户LETENO, 密码PASSWORD,赋予的权限是:all

(all 这个应该是跟操作grant的用户有关,如果是root,则为root权限)

ON *.* 表示所有表,第一个* 应该表示数据库?抑或是创建数据库的人?(待考证,应该是前者), 
因为记得在Oracle中识别一个表需要的不仅仅是表名,还有创建者,如leteno.student_list(难不成Oracle是用创建表的用户作为表所存的数据库名(命名空间?)))

//2015.06.07
*.*,第一个*表示数据库名。


创建数据库:

[code]CREATE DATABASE LETENO_DB;
USE LETENO_DB
创建数据库LETENO_DB,以及切换到LETENO_DB数据库。


创建表:

[code]CREATE TABLE student ( 
    sno int(11) NOT NULL auto_increment, 
    sname varchar(30), 
    age int(11), 
    PRIMARY KEY (sno) 
);


注意:此处的auto_increment,本人尝试过一开始直接添加学生的sno=100,接下来默认添加的学生的sno为101 102… 又再添加学生sno为1,默认添加的学生为103 104…

要想重置auto_increment:

ALTER TABLE student AUTO_INCREMENT=1;


貌似这个还要看mysql的类型,我的不能用。。。

看来还是oracle比较底层,可以操纵sequence实现increment的起始,步长等。(可能还没学到mysql内部的操作)

类型

此处仅列举标准SQL类型,目的是为了标准化,规范化。

类型关键字注意事项
布尔BOOL取值有TRUE FALSE NULL
字符CHAR CHAR(N) VARCHAR(N)VARCHAR是可变长数组,而CHAR得恰好有N个字符。
数值INT DOUBLE NUMERIC(P,S)P代表总共有多少位数字,S代表其中小数部分多少位。比double精确,效率会较慢,毕竟得检查。
时间DATE DATETIME TIME TIMESTAMP常见的是TIMESTAMP 存储1970 - 2037年之间的时间戳(时间这么短,原因1,用32位存储;*原因2,时间用秒计),注意使用DATE DATETIME得小心,最好先查阅手册
自增长AUTO_INCREMENT只能是主键的属性
空值NULL 、 NOT NULL色即是空空
主键PRIMARY KEY其物理含义是该字段是唯一的,不存在相同的

增删改查:

[code]INSERT INTO student (sno, sname, age) VALUES (1, 'leteno', 13);
DELETE FROM student WHERE SNAME=‘TEMP’;
UPDATE student SET AGE = 18 WHERE SNO=2;
SELECT * FROM student WHERE SNAME='LETENO';


*1)增加的还有另外一种方式:

INSERT INTO student values(1, ‘leteno’, 13);

不过不常用,它里面的属性值必须一一对应,而且不得缺漏(否则,会报:Column count doesn’t match value count)

*2)表名的大小写敏感,也就是STUDENT 会报:Table ‘LETENO_DB.STUDENT’ does not exist(.前面是数据库的名字。。。),(*但是列名确是大小写不分,age与AGE,而且连字段值也不分大小写,leteno与LETENO)

**3)使字段值区分大小写:(对字段添加一个binary属性)

[code]1)创建时: ... sname varchar(30) binary, ...
2)ALTER TABLE student MODIFY COLUMN sname varchar(30) BINARY;


进阶:

mysql命令

这些命令在shell中执行,mysql命令可以在 mysql> 中执行,这些命令在shell中都有选项-u < .username > -p <.password>(password 一般不连同指令一块出现,不安全,一般省去,在下面noecho输入),一般当你输入下面的命令时都会被deny,没权限,得登陆 (后接-u <.username> -p)

1)myisamchk命令

与修复相关,其中isam是Indexed Sequence Access Method,因为基于索引,所以查找方便。

(仍然未知,先空着)

2)mysql 命令:

最有用的 应该是:

[code]status  显示服务器状态信息
edit    打开默认编辑器(一般为vi),在里面编辑sql语句,wq后分号执行上述语句。
source  后接filename,执行filename里面的SQL语句。
tee     后接filename,将终端所有输出包括指令输出到filename中(这个是双向重定向,输出内容在filename,终端中都会出现)。


3)mysqladmin

[code]create/drop <database>
status      与mysql命令的不同,此处显示的是整个mysql服务器的状态,比如queries per second
            (而mysql命令在mysql> 中是表示当前DB的状态, 在shell中表示的是一些Variables)
shutdown    停止服务器
ping        查看服务器是否关闭一般返回 mysqld is alive


4)mysqldump

这个指令是将数据库文件全部(包括数据)或部分以SQL命令集合的方式输出,指令如下:

[code]mysqldump -u <username> -p <database name> > file.store
如 mysqldump -u root -p mysql > mysql.dump


意外发现数据库“mysql”中有表’db‘, select全部一下,发现有我之前创立的数据库LETENO_DB,也就是说,所有数据库都将在mysql.db中保存,里面的字段包括Host, User,Db, 还有各种privilege。估计该表保存的是一个用户(User@Host)对于数据库(Db)的操作的权限(privilege)

下面是部分截图:




mysqldump命令还有一些选项:

[code]-e  使用扩展的insert语法,能加快转储数据的加载速度 
-t  只转储表中的数据(DML?)
-d  只转储表的结构(DDL?)


注:

1)观摩了一下扩展的,应该是这么写的INSERT INTO student values (1,’ZHENG‘, 13), (2, ’LETENO‘,11),(3,’YOUNG‘,33);

2)发现他们添加数据(INSERT)的时候,先把表锁住 LOCK TABLES ’student‘ WRITE;在解锁UNLOCK TABLES;(此处估计应该写成UNLOCK TABLES ‘student’ 尝试了一下,不行,得只能用UNLOCK TABLES)

2.1)不过,尝试了一下lock之后在其他地方(另开终端)insert,无反应,直到我unlock之后才能添加进去。

2.2)尝试了unlock tables student read;发现“然并卵”,难不成select不属于表的读取(read)的范畴?那会是什么呢?

2.3)我又尝试在lock之后在另外一处也lock一下,发现无反应,也就是说这个是独占锁。

2.4)这个锁的粒度是进程,不是用户,当我另开终端,以同样的用户登入,发现还是操作不了,被锁上,等待解锁。

5)mysqlimport

与上面的指令是逆过程,参数是 文本文件 + 数据库名字

其实可以通过在mysql> 下:

[code]mysql> create database NEW_DB
mysql> source mysql.dump.file


6) mysqlshow

一般需要用户登入(-u username -p),作用是:快速查看mysql的详细信息,如里面的数据库等等

直接上图:(我这里的用户proxy是咩有密码的)












参数结果
无参列出所有可用的数据库
一个数据库为参数列出该数据库中的表
数据库和表名为参数列出表中的列
数据库、表和列为参数列出指定列的详细信息

其他命令:

1) grant 命令

详情看 编码 > 创建新用户

2)revoke 命令

revoke <privilege> on <tables> from <user>


REVOKE INSERT ON LETENO_DB.* FROM proxy;


注: revoke 只能撤回用户的权利,要完全删除用户,你得在mysql.user表中删除相应的用户记录。

[code]mysql> DELETE FROM mysql.user WHERE user = "proxy"
mysql> FLUSH PRIVILEGES


单纯使用上面俩语句,是无法完全清除proxy用户的痕迹的。(当然,proxy无法再次登陆)但是对于数据库表的操作权限还没清除干净,可以通过
select * from mysql.db where User="proxy"
发现,仍然有proxy的痕迹,而且此时调用revoke撤proxy的权,发现报Error 1141:
There is no such grant defined for user 'proxy' on host '%'
;估计是查找user表时发现查无此人(其实user表也是有权限priv字段的);所以说删除用户时要有一定顺序,先撤权,再删人。否则会删不干净的。

其实也未必,不能使用revoke,就使用最古老最简单的方法:delete

delete from mysql.db where user='proxy'


这样就删干净了。。。。

3)密码相关:

修改用户密码可以通过直接修改mysql.user中对应的字段达到目的,只不过一般密码都是加密过的,直接设置有些欠妥。所以mysql提供
password(<password>)
方法对密码加密,范例如下:

[code]UPDATE mysql.user SET password=password("newpassword") WHERE user="proxy";


C语言访问MySQL数据库

1)编译

[code]gcc -o a.out connect1.c -I/usr/include/mysql -L/usr/lib/mysql -lmysqlclient


2)编程

初始化:MYSQL*
mysql_init(MYSQL *)


连接:MYSQL*

[code]mysql_real_connect( MYSQL *connection, 
                    const char *server_host, 
                    const char *sql_user_name, 
                    const char *sql_password, 
                    const char *db_name, 
                    unsigned int port_number,
                    const char *unix_socket_name,
                    unsigned int flags);


关闭连接

mysql_close(MYSQL *connection);

例程:

[code]#include <stdlib.h>
#include <stdio.h>

#include "mysql.h"

int main(int argc, char *argv[]) 
{
  MYSQL *conn_ptr;

  conn_ptr = mysql_init(NULL);
  if (!conn_ptr) 
  {
    fprintf(stderr, "mysql_init failed\n");
    return EXIT_FAILURE;
  }

  conn_ptr = mysql_real_connect(conn_ptr,
                                "localhost",
                                "proxy",
                                NULL,
                                "LETENO_DB",
                                0,
                                NULL,
                                0);

  if (conn_ptr)
  {
    printf("Connection success\n");
  } else 
  {
    printf("Connection failed\n");
  }

  mysql_close(conn_ptr);

  return EXIT_SUCCESS;  
}


错误处理:

unsigned int mysql_errno(MYSQL *connection) 

char *mysql_error(MYSQL *connection)


执行mysql语句

int mysql_query(MYSQL *connection, const char *query)


受影响行数:

my_ulonglong mysql_affected_rows(MYSQL *connection)


获得resultset:

MYSQL_RES * mysql_store_result(MYSQL*);

一般用于mysql_query之后

取得resultset的一行结果,相当于resultset.next()

MYSQL_ROW mysql_fetch_row(MYSQL_RES)

其中MYSQL_ROW 是一个数组,数组的元素对应着查询的每个结果,也就是MYSQL_ROW[i] == mysqlrow.getString(i);

至于数组的大小:

int mysql_field_count(MYSQL*);

还能获得结果集的每个字段的属性:

MYSQL_FIELD * mysql_fetch_field(MYSQL_RES*)

其中 MYSQL_FIELD {

char *name;

char *table;

int type;

int length;

int flags; (列定义的标志,例如自增长AUTO_INCREMENT_FLAG 区分大小写BINARY_FLAG)

}

例子程序:

[code]#include <stdlib.h>
#include <stdio.h>

#include "mysql.h"

MYSQL my_connection;
MYSQL_RES *res_ptr;
MYSQL_ROW sqlrow;

void display_header();
void display_row();

int main(int argc, char *argv[]) {
  int res;
  int first_row = 1;

  mysql_init(&my_connection);
  if (mysql_real_connect(&my_connection,
                         "localhost",
                         "proxy",
                         NULL,
                         "LETENO_DB",
                         0,
                         NULL,
                         0)) {

    printf("Connection success\n");

    res = mysql_query(&my_connection,
                      "SELECT sno, sname, age FROM student WHERE age>5");

    if (res) {
      printf("SELECT error: %s\n", mysql_error(&my_connection));
    } else {
      res_ptr = mysql_store_result (&my_connection);
      if (res_ptr) {

        while((sqlrow = mysql_fetch_row(res_ptr))) {
          if (first_row) {
            display_header();
            first_row = 0;
          }
          display_row();
        }
      }

      if (mysql_errno(&my_connection)) {
          fprintf(stderr, "Retrive error: %s\n", mysql_error(&my_connection));
      }
       mysql_free_result(res_ptr);
  }

    mysql_close(&my_connection);
} else {
      fprintf(stderr, "Connection failed\n");
      if (mysql_errno(&my_connection)) {
        fprintf(stderr, "Connection error %d: %s\n",
                mysql_errno(&my_connection), mysql_error(&my_connection));
      }
 }
    return EXIT_SUCCESS;
}

void display_header() {

  MYSQL_FIELD *field_ptr;

  printf("Column details:\n");
  while ((field_ptr = mysql_fetch_field(res_ptr)) != NULL) {
    printf("\t Name: %s\n", field_ptr->name);
    printf("\t Type: ");
    if (IS_NUM(field_ptr->type)) {
      printf("Numeric field\n");
    } else {
      switch(field_ptr->type) {
      case FIELD_TYPE_VAR_STRING:
        printf("VARCHAR\n");
      break;
      case FIELD_TYPE_LONG:
        printf("LONG\n");
      break;
      default:
        printf("Type is %d, check in mysql_com.h", field_ptr->type);
      }
    }

    printf("\t Max width %ld\n", field_ptr->length);
    if (field_ptr->flags & AUTO_INCREMENT_FLAG)
      printf("\t Auto increments\n");
    printf("\n");
  }
}

void display_row(){
  unsigned int field_count;

  field_count = 0;

  while (field_count < mysql_field_count(&my_connection)) {
    printf("%s ", sqlrow[field_count]);
    field_count ++;
  }
  printf("\n");
}


疑难杂症:

Table ‘LETENO_DB.STUDENT’ does not exist:

mysql的表都有“命名空间”,也就是数据库名。比如你这个表是放置在DB数据库下:

方法1) use DB

方法2) 使用里面的表(比如student)时, 写上全称DB.student
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: