mirror of
https://github.com/beyondx/Notes.git
synced 2026-02-03 18:33:26 +08:00
Add New Notes
This commit is contained in:
115
Zim/Programme/python/sql/Python操作SQLite备忘.txt
Normal file
115
Zim/Programme/python/sql/Python操作SQLite备忘.txt
Normal file
@@ -0,0 +1,115 @@
|
||||
Content-Type: text/x-zim-wiki
|
||||
Wiki-Format: zim 0.4
|
||||
Creation-Date: 2011-10-09T21:22:33+08:00
|
||||
|
||||
====== Python操作SQLite备忘 ======
|
||||
Created Sunday 09 October 2011
|
||||
http://www.2cto.com/kf/201103/85992.html
|
||||
|
||||
SQLite,是一款轻型的数据库,它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。
|
||||
|
||||
它能够支持Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如 Tcl、C#、PHP、Java等,还有ODBC接口。
|
||||
|
||||
PS:单数据存储文件(类似微软的Access),支持数据库大小至2TB,支持多种开发语言,C, PHP, Perl, Java, ASP .NET,Python。
|
||||
|
||||
|
||||
Python操作SQLite的库PySQLite已经被包括在Python2.5以后的标准库中了,可以方便的使用。
|
||||
|
||||
下面是Python操作SQLite的示例代码:
|
||||
|
||||
|
||||
# coding:utf-8
|
||||
# Practice of oprating SQLite with Python
|
||||
# by redice 2010.11.09
|
||||
|
||||
import sys
|
||||
reload(sys)
|
||||
sys.setdefaultencoding(utf-8)
|
||||
|
||||
import sqlite3
|
||||
|
||||
# 连接数据库,数据库文件不存在则创建
|
||||
conn = sqlite3.connect("users.db")
|
||||
conn.text_factory = lambda x: unicode(x, utf-8, replace)
|
||||
curs = conn.cursor()
|
||||
|
||||
# 检查users表是否存在,不存在则创建
|
||||
# 很强大,不需要使用管理工具事先创建
|
||||
curs.execute(CREATE TABLE if not exists users(username VARCHAR(20) UNIQUE,password VARCHAR(32),groupe INTEGER);)
|
||||
# 对数据库有修改的操作要调用commit提交事务
|
||||
conn.commit()
|
||||
|
||||
# insert data
|
||||
# 采用这种方法插入数据,不用担心数据要转义。数据库接口会自动帮你转义
|
||||
curs.execute("insert into users values(?,?,?);", (redice,123456,1))
|
||||
curs.execute("insert into users values(?,?,?);", (qipeng,123456,0))
|
||||
curs.execute("insert into users values(?,?,?);", (zhangsan,123456,0))
|
||||
curs.execute("insert into users values(?,?,?);", (laowu,123456,0))
|
||||
curs.execute("insert into users values(?,?,?);", (lisi,123456,0))
|
||||
curs.execute("insert into users values(?,?,?);", (wangwu,123456,0))
|
||||
conn.commit()
|
||||
|
||||
# 查找数据
|
||||
# 对数据库没有修改的操作不需要用commit提交事务
|
||||
curs.execute("select * from users where username=?;" ,(raw_input("请输入要查询的用户名称:"),))
|
||||
row = curs.fetchone()
|
||||
if row:
|
||||
print row
|
||||
|
||||
conn.close()
|
||||
|
||||
运行结果:
|
||||
|
||||
==================================
|
||||
|
||||
import pysqlite2.dbapi2 as sqlite
|
||||
|
||||
def runTest():
|
||||
cx = sqlite.connect('test.db')
|
||||
cu = cx.cursor()
|
||||
|
||||
#create
|
||||
cu.execute('''create table catalog(
|
||||
id integer primary key,
|
||||
pid integer,
|
||||
name varchar(10) unique
|
||||
)''')
|
||||
|
||||
#insert
|
||||
cu.execute('insert into catalog values(0,0,"张小山")')
|
||||
cu.execute('insert into catalog values(1,0,"hello")')
|
||||
cx.commit()
|
||||
|
||||
#select
|
||||
cu.execute('select * from catalog')
|
||||
print '1:',
|
||||
print cu.rowcount
|
||||
rs = cu.fetchmany(1)
|
||||
print '2:',
|
||||
print rs
|
||||
rs = cu.fetchall()
|
||||
print '3:',
|
||||
print rs
|
||||
|
||||
#delete
|
||||
cu.execute('delete from catalog where id = 1 ')
|
||||
cx.commit()
|
||||
|
||||
|
||||
cu.execute('select * from catalog')
|
||||
rs = cu.fetchall()
|
||||
print '4:',
|
||||
print rs
|
||||
|
||||
#select count
|
||||
cu.execute("select count(*) from catalog")
|
||||
rs = cu.fetchone()
|
||||
print '5:',
|
||||
print rs
|
||||
|
||||
|
||||
cu.execute("select * from catalog")
|
||||
cu.execute('drop table catalog')
|
||||
|
||||
if __name__ == '__main__':
|
||||
runTest()
|
||||
152
Zim/Programme/python/sql/mysql.txt
Normal file
152
Zim/Programme/python/sql/mysql.txt
Normal file
@@ -0,0 +1,152 @@
|
||||
Content-Type: text/x-zim-wiki
|
||||
Wiki-Format: zim 0.4
|
||||
Creation-Date: 2011-10-17T00:43:21+08:00
|
||||
|
||||
====== mysql ======
|
||||
Created Monday 17 October 2011
|
||||
|
||||
MySQL Tutorial: Install, Create DB and Table, Insert and Select Records
|
||||
|
||||
This MySQL jumpstart guide will get you running quickly on the basics. This explains how to install MySQL, create a sample database, create a table, insert records into the table, and select records from the table.
|
||||
|
||||
===== 1. Install and Configure MySQL =====
|
||||
|
||||
Go to the MySQL download page, and select your appropriate platform to download the latest version of MySQL community server.
|
||||
|
||||
* If you are installing on RedHat based distro (for example: CentOS), follow this article: Install MySQL on Linux using rpm
|
||||
* You can also use yum groupinstall to install the MySQL Database group.
|
||||
* If you want to install MySQL along with the other components of the LAMP stack (Apache, and PHP), follow this article: How to install or upgrade LAMP
|
||||
|
||||
===== 2. Create MySQL Database =====
|
||||
|
||||
Once MySQL is installed, connect to it using MySQL root user and create the database as shown below.
|
||||
|
||||
**# mysql -u root -p**
|
||||
**Enter password:**
|
||||
**mysql>**
|
||||
|
||||
After connecting as MySQL root user, execute the following command from the “mysql> ” prompt to create a database.
|
||||
|
||||
The following command will create the database called “thegeekstuff”.
|
||||
|
||||
**mysql> create database thegeekstuff**
|
||||
|
||||
Use “show databases” command to verify that the database was created successfully.
|
||||
|
||||
**mysql> show databases;**
|
||||
**+--------------------+**
|
||||
**| Database |**
|
||||
**+--------------------+**
|
||||
**| information_schema |**
|
||||
**| mysql |**
|
||||
**| thegeekstuff |**
|
||||
**+--------------------+**
|
||||
**3 rows in set (0.00 sec)**
|
||||
|
||||
|
||||
===== 3. Create MySQL Table =====
|
||||
|
||||
**Connect **to the newly created database using “use” command before you can perform any operation in the database.
|
||||
|
||||
To connect to the database, do the following.
|
||||
|
||||
**mysql> use thegeekstuff;**
|
||||
**Database changed**
|
||||
|
||||
The following example creates a employee table.
|
||||
|
||||
**create table employee (**
|
||||
**id INT AUTO_INCREMENT PRIMARY KEY,**
|
||||
**name varchar(20),**
|
||||
**dept varchar(10),**
|
||||
**salary int(10)**
|
||||
**)**__;__
|
||||
|
||||
When you copy-paste the above create table command in the “mysql> ” prompt, it will display the continuation prompt “->” starting from the 2nd line, which indicates that the command is still not over. The end of a SQL command is identified by a **semi-colon**.
|
||||
|
||||
**mysql> create table employee (**
|
||||
** -> id INT AUTO_INCREMENT PRIMARY KEY,**
|
||||
** -> name varchar(20),**
|
||||
** -> dept varchar(10),**
|
||||
** -> salary int(10)**
|
||||
** -> );**
|
||||
**Query OK, 0 rows affected (0.00 sec)**
|
||||
|
||||
You can also use any one of the following data types.
|
||||
|
||||
* dcode** SMALLINT**
|
||||
* mcode **MEDIUMIN**
|
||||
* project_start **DATE**
|
||||
* loggedon** TIME**
|
||||
|
||||
Do the following to view all the tables available in the database.
|
||||
|
||||
**mysql> show tables;**
|
||||
**+------------------------+**
|
||||
**| Tables_in_the geekstuff |**
|
||||
**+------------------------+**
|
||||
**| employee |**
|
||||
**+------------------------+**
|
||||
**1 row in set (0.00 sec)**
|
||||
|
||||
To view the table //description,// do the following.
|
||||
|
||||
**mysql> desc employee;**
|
||||
**+--------+-------------+------+-----+---------+----------------+**
|
||||
**| Field | Type | Null | Key | Default | Extra |**
|
||||
**+--------+-------------+------+-----+---------+----------------+**
|
||||
**| id | int(11) | NO | PRI | NULL | auto_increment |**
|
||||
**| name | varchar(20) | YES | | NULL | |**
|
||||
**| dept | varchar(10) | YES | | NULL | |**
|
||||
**| salary | int(10) | YES | | NULL | |**
|
||||
**+--------+-------------+------+-----+---------+----------------+**
|
||||
**4 rows in set (0.01 sec)**
|
||||
|
||||
===== 4. Insert Records into a Table =====
|
||||
|
||||
Use the following sample insert commands to insert some records to the employee table. While inserting values to //all //the columns in the table, you don’t need to specify the column name. Just specify the values in the same sequence as the column names.
|
||||
|
||||
**insert into employee values(100,'Thomas','Sales',5000);**
|
||||
**insert into employee values(200,'Jason','Technology',5500);**
|
||||
**insert into employee values(300,'Mayla','Technology',7000);**
|
||||
**insert into employee values(400,'Nisha','Marketing',9500);**
|
||||
**insert into employee values(500,'Randy','Technology',6000);**
|
||||
|
||||
To insert values only to specific columns, you should specify the// column names //as shown below.
|
||||
|
||||
**mysql> insert into employee(name,dept) values('Ritu', 'Accounting');**
|
||||
**Query OK, 1 row affected (0.01 sec)**
|
||||
|
||||
Note: You can also upload data from a text file to MySQL database using **mysqlimport **command.
|
||||
|
||||
===== 5. Query Records from a Table =====
|
||||
|
||||
To view all the records from a table, use the following select statement.
|
||||
http://www.thegeekstuff.com/2011/10/mysql-tutorial-basics/?utm_source=feedburner&utm_medium=email&utm_campaign=Feed%3A+TheGeekStuff+%28The+Geek+Stuff%29
|
||||
**mysql> select * from employee;**
|
||||
**+-----+--------+------------+--------+**
|
||||
**| id | name | dept | salary |**
|
||||
**+-----+--------+------------+--------+**
|
||||
**| 100 | Thomas | Sales | 5000 |**
|
||||
**| 200 | Jason | Technology | 5500 |**
|
||||
**| 300 | Mayla | Technology | 7000 |**
|
||||
**| 400 | Nisha | Marketing | 9500 |**
|
||||
**| 500 | Randy | Technology | 6000 |**
|
||||
**| 501 | Ritu | Accounting | NULL |**
|
||||
**+-----+--------+------------+--------+**
|
||||
**6 rows in set (0.00 sec)**
|
||||
|
||||
To view only a specific columns from a table, specify the column names in the select command.
|
||||
|
||||
**mysql> select name, dept from employee;**
|
||||
|
||||
The following select statement has a where condition which displays the employee records who belong to Technology department and getting a salary >= 7000.
|
||||
|
||||
**mysql> select * from employee where dept = 'Technology' and salary >= 6000;**
|
||||
**+-----+--------+------------+--------+**
|
||||
**| id | name | dept | salary |**
|
||||
**+-----+--------+------------+--------+**
|
||||
**| 300 | Mayla | Technology | 7000 |**
|
||||
**| 500 | Randy | Technology | 6000 |**
|
||||
**+-----+--------+------------+--------+**
|
||||
**2 rows in set (0.00 sec)**
|
||||
141
Zim/Programme/python/sql/python之sqlite3使用详解.txt
Normal file
141
Zim/Programme/python/sql/python之sqlite3使用详解.txt
Normal file
@@ -0,0 +1,141 @@
|
||||
Content-Type: text/x-zim-wiki
|
||||
Wiki-Format: zim 0.4
|
||||
Creation-Date: 2011-10-09T21:36:14+08:00
|
||||
|
||||
====== python之sqlite3使用详解 ======
|
||||
Created Sunday 09 October 2011
|
||||
http://anony3721.blog.163.com/blog/static/5119742010716104442536/
|
||||
|
||||
Python SQLITE数据库是一款非常小巧的嵌入式开源数据库软件,也就是说没有独立的维护进程,所有的维护都来自于程序本身。它使用一个文件存储整个数据库,操作十分方便。它的最大优点是使用方便,功能相比于其它大型数据库来说,确实有些差距。但是性能表现上,SQLITE并不逊色。麻雀虽小,五脏俱全, sqlite 实现了多数 sql-92 的标准,比如说 transaction 、 trigger 和复杂的查询等。
|
||||
|
||||
python的数据库模块有统一的接口标准,所以数据库操作都有统一的模式,基本上都是下面几步(假设数据库模块名为db):
|
||||
|
||||
1. 用db.connect创建数据库连接,假设连接对象为conn
|
||||
2. 如果该数据库操作不需要返回结果,就直接用conn.execute查询,根据数据库事务隔离级别的不同,可能修改数据库需要conn.commit
|
||||
3. 如果需要返回查询结果则用conn.cursor创建游标对象cur, 通过cur.execute查询数据库,用cur.fetchall/cur.fetchone/cur.fetchmany返回查询结果。根据数据库事 务隔离级别的不同,可能修改数据库需要conn.commit
|
||||
4. 关闭cur, conn
|
||||
|
||||
下面让我们一步步走进Python中的SQLite吧。
|
||||
|
||||
===== 一,Python SQLITE数据库导入模块: =====
|
||||
|
||||
import sqlite3
|
||||
|
||||
===== 二,创建数据库/打开数据库: =====
|
||||
|
||||
cx = sqlite3.connect("E:/test.db") 其实我们不需要显式的创建一个sqlite数据库,在调用connect函数的时候,指定库名称,如果指定的数据库存在就直接打开这个数据库,如果不存在就新创建一个再打开。这一点应用很好理解。
|
||||
|
||||
===== 三,数据库连接对象: =====
|
||||
|
||||
打开数据库时返回的对象cx就是一个数据库连接对象,它可以有以下操作:
|
||||
|
||||
commit()--事务提交 rollback()--事务回滚 close()--关闭一个数据库连接 cursor()--创建一个游标
|
||||
|
||||
===== 四,Python SQLITE数据库游标的使用: =====
|
||||
|
||||
游标提供了一种对从表中检索出的数据进行操作的灵活手段,就本质而言,游标实际上是一种能从包括多条数据记录的__结果集__中每次提取**一条记录**的机制。游标总是与**一条SQL 选择语句相关联**。因为游标由**结果集**(可以是零条、一条或由相关的选择语句检索出的多条记录)和结果集中指向**特定记录的游标位置**组成。当决定对结果集进行处理时,必须声明一个指向该结果集的游标。如果曾经用 C 语言写过对文件进行处理的程序,那么游标就像您打开文件所得到的文件句柄一样,只要文件打开成功, 该文件句柄就可代表该文件。对于游标而言,其道理是相同的。可见游标能够实现按与传统程序读取**平面文件**类似的方式处理来自基础表的结果集,从而把表中数据以平面文件的形式呈现给程序。
|
||||
|
||||
我们知道关系数据库管理系统实质是面向集合的,在Sqlite中并没有一种描述表中单一记录的表达形式,除非使用where 子句来限制只有一条记录被选中。因此我们必须借助于游标来进行面向单条记录的数据处理。由此可见,游标允许应用程序对查询语句select 返回的行结果集中**每一行进行相同或不同的操作**,而不是一次对整个结果集进行同一种操作;它还提供对基于游标位置而对表中数据进行删除或更新的能力;正是游标把作为__面向集合的数据库管理系统和面向行的程序设计__两者联系起来,使两个数据处理方式能够进行沟通。
|
||||
|
||||
下面着重阐述cursor游标的使用。其实,所有sql语句的执行都要在游标对象下进行。
|
||||
|
||||
==== 首先,定义一个游标: ====
|
||||
|
||||
cu = cx.cursor() 这样定义了一个游标。游标对象有以下的操作:
|
||||
|
||||
execute()--执行sql语句 executemany--执行多条sql语句 close()--关闭游标 fetchone()--从结果中取一条记录,并将游标指向下一条记录 fetchmany()--从结果中取多条记录 fetchall()--从结果中取出所有记录 scroll()--游标滚动
|
||||
|
||||
下面就使用Python SQLITE数据库中游标对我们上面建立的数据库作一些操作吧:
|
||||
|
||||
===== 1,建表: =====
|
||||
cu.execute('create table catalog (id integer primary key,pid integer,name varchar(10) UNIQUE)') 上面语句创建了一个叫catalog的表,它有一个主键id,一个pid,和一个name,name是不可以重复的。
|
||||
|
||||
===== 2,插入数据: =====
|
||||
cu.execute("insert into catalog values(0, 0, 'name1')")
|
||||
cu.execute("insert into catalog values(1, 0, 'hello')")
|
||||
简单的插入两行数据,不过需要提醒的是,只有**提交了之后,才能生效**.我们使用数据库**连接对象cx**来进行提交commit和回滚rollback操作.
|
||||
cx.commit()
|
||||
|
||||
===== 3,查询: =====
|
||||
cu.execute("select * from catalog") 要提取查询到的数据,使用游标的fetch***函数,如:
|
||||
print cu.fetchall() 返回结果如下:
|
||||
[(0, 0, u'name1'), (1, 0, u'hello')]
|
||||
如果我们使用cu.fetchone(),则首先返回列表中的第一项,再次使用,则返回第二项,依次下去.
|
||||
|
||||
===== 4,修改: =====
|
||||
cu.execute("update catalog set name='name2' where id = 0")
|
||||
cx.commit() 注意,修改数据以后提交
|
||||
|
||||
===== 5,删除: =====
|
||||
cu.execute("delete from catalog where id = 1")
|
||||
cx.commit()
|
||||
|
||||
以上简单的操作反应的Python SQLITE数据库操作的基本要点,这里点到为止.然后,SQLite的强大,并不仅限于此,其对SQL高级特性的支持及其小巧灵活的特点,使得SQLite在众多领域受到开发者的青睐.
|
||||
|
||||
===== 举例: =====
|
||||
|
||||
=== Exemplary exemplar 1 ===
|
||||
|
||||
import sqlite3
|
||||
|
||||
con = sqlite3.connect('d:/mydatabase.db3')
|
||||
cur = con.cursor()
|
||||
cur.execute('CREATE TABLE foo (o_id INTEGER PRIMARY KEY, fruit VARCHAR(20), veges VARCHAR(30))')
|
||||
con.commit()
|
||||
cur.execute('INSERT INTO foo (o_id, fruit, veges) VALUES(NULL, "apple", "broccoli")')
|
||||
con.commit()
|
||||
print cur.lastrowid
|
||||
|
||||
cur.execute('SELECT * FROM foo')
|
||||
print cur.fetchall()
|
||||
|
||||
==== Exemplary exemplar 2 ====
|
||||
|
||||
#-*- encoding:gb2312 -*-
|
||||
import sqlite3
|
||||
|
||||
conn = sqlite3.connect("D:/aaa.db")
|
||||
conn.isolation_level = None #这个就是事务隔离级别,默认是需要自己commit才能修改数据库,置为None则自动每次修改都提交,否则为""
|
||||
# 下面就是创建一个表
|
||||
conn.execute("create table if not exists t1(id integer primary key autoincrement, name varchar(128), info varchar(128))")
|
||||
# 插入数据
|
||||
conn.execute("insert into t1(name,info) values ('zhaowei', 'only a test')")
|
||||
# 如果隔离级别不是自动提交就需要手动执行commit
|
||||
conn.commit()
|
||||
# 获取到游标对象
|
||||
cur = conn.cursor()
|
||||
# 用游标来查询就可以获取到结果
|
||||
cur.execute("select * from t1")
|
||||
# 获取所有结果
|
||||
res = cur.fetchall()
|
||||
print 'row:', cur.rowcount
|
||||
**# cur.description是对这个表结构的描述**
|
||||
print 'desc', cur.description
|
||||
# 用fetchall返回的结果是一个二维的列表
|
||||
for line in res:
|
||||
for f in line:
|
||||
print f,
|
||||
print
|
||||
print '-'*60
|
||||
|
||||
cur.execute("select * from t1")
|
||||
# 这次查询后只取一个结果,就是一维列表
|
||||
res = cur.fetchcone()
|
||||
print 'row:', cur.rowcount
|
||||
for f in res:
|
||||
print f,
|
||||
print
|
||||
# 再取一行
|
||||
res = cur.fetchone()
|
||||
print 'row:', cur.rowcount
|
||||
for f in res:
|
||||
print f,
|
||||
print
|
||||
print '-'*60
|
||||
|
||||
|
||||
cur.close()
|
||||
conn.close()
|
||||
--
|
||||
Anony
|
||||
专注的力量成就梦想
|
||||
125
Zim/Programme/python/sql/浅谈MySQL外键.txt
Normal file
125
Zim/Programme/python/sql/浅谈MySQL外键.txt
Normal file
@@ -0,0 +1,125 @@
|
||||
Content-Type: text/x-zim-wiki
|
||||
Wiki-Format: zim 0.4
|
||||
Creation-Date: 2011-10-17T10:45:11+08:00
|
||||
|
||||
====== 浅谈MySQL外键 ======
|
||||
Created Monday 17 October 2011
|
||||
http://www.xiaoxiaozi.com/2009/07/12/1158/
|
||||
|
||||
像MySQL这样的关系型数据库管理系统,它们的基础是在数据库的**表之间创建关系**的能力。通过方便地在不同表中建立**记录到记录的联系**,RDBMS可以利用不同的方法分析数据,同时保持数据库以系统的方式、最小的冗余进行组织。
|
||||
|
||||
===== 简单描述: =====
|
||||
这些关系基本上依靠__外键__进行管理,在关系中**所有表中具有相同含义的字段作为公共部分来连接不同表中的记录**。外键可以是一对一的,一个表的记录只能与另一个表的一条记录连接,或者是一对多的,一个表的记录与另一个表的多条记录连接。
|
||||
|
||||
MySQL中**“键”和“索引”的定义相同**, 所以外键和__主键__一样也是索引的一种。不同的是MySQL会**自动为所有表的主键进行索引**,但是外键字段必须由用户进行明确的索引。这和一些封建思想比较沉重的家庭是一样的,外来的孩子(儿媳妇,倒插门女婿)一般都是不受重视的。
|
||||
|
||||
===== 低俗示例: =====
|
||||
**表间一对一关系示例:**
|
||||
|
||||
有两张表,第一张表是记录公司有多少人,都有谁,也就是员工编号及员工姓名这些基本表。另一张表记录每个月发给用户多少工资,所谓工资表是也。
|
||||
|
||||
但是工资表里面不能以员工姓名为主键,同样要通过员工id,因为员工的姓名是可能重复的啊。部门经理叫张三,小弟也叫张三,那这俩张三的工资能一样吗?并且员工表里面的每个人都有工资,否则谁也不给你干活,且一个人只能有一份工资,否则老板也不同意了。所以员工表和工资表是通过员工id进行关联的一对一关系。
|
||||
|
||||
不过我们要有一个好的价值观,我们上班不能为了钱,我们是为了学知识,学文化,为早日实现四个现代化(别问我是啥,也别问我到底实现没有)而努力奋斗。所以在工资表里如果没有你也不要乱喊。嗯。
|
||||
/*
|
||||
建立员工表
|
||||
*/
|
||||
create table employees (
|
||||
id int(5) not null auto_increment ,
|
||||
name varchar(8) not null,
|
||||
primary key (id)
|
||||
)
|
||||
type=innodb;
|
||||
|
||||
/*
|
||||
建立工资表
|
||||
*/
|
||||
create table payroll(
|
||||
id int(5) not null,
|
||||
emp_id int(5) not null,
|
||||
name varchar(8) not null,
|
||||
payroll float(4,2) not null,
|
||||
primary key(id),
|
||||
**index **emp_id (emp_id),
|
||||
foreign key (emp_id) references employees (id)
|
||||
)
|
||||
type = innodb;
|
||||
|
||||
**表间一对多关系示例:**
|
||||
|
||||
有两个表,一个是贪官表,有贪官的id和名字。另有一张贪官情妇表,注意一个贪官不一定只有一个情妇,其有个二三四五奶是很正常的,所以在贪官表里面的一条数据,对应情妇表里可能就有多条记录,这是通过**贪官id**进行关联的一对多关系。
|
||||
**这里的一指的是作为参考表中的字段----贪官ID, 这里的多指的是情妇表中的外键即情妇表中的不同记录的外键值相同。**
|
||||
|
||||
==== 参照完整性(对于有外键的表而言): ====
|
||||
|
||||
当外键与另一个表的字段有关系,而且这种关系**是惟一**时,这个系统就称为处于参照完整性的状态。也就是说,如果一个字段在所有的表中只出现一次,而且每个表的这个字段的变化都会影响其他表,这就是存在参照完整性。
|
||||
|
||||
术语理解上可能不太方便,其实就是说__要在有外键的表中保持所有数据的一致性(当此外键对应的参考表中的相应字段发生变化时,这种变化也要反映到含有外键的表)__。比如说“张三”离职了,在员工表里面肯定没有这个人了,可是如果在工资表里面还存在这个孩子,那么老大就会很生气的。
|
||||
|
||||
另外,比如说一个县官,因为一些小政绩,由县官变成了知府,那么他的那些情妇的地位也要调整一下,最起码得从县官二奶改为知府二奶,否则这位二奶也是不会同意的。
|
||||
|
||||
===== MySQL的外键只能在InnoDB表中使用: =====
|
||||
|
||||
当今主流数据库都会**自动考虑**参照完整性的问题。当你更新或删除数据时(参照表),其会把**相关联的表中(外键表)**数据也都给你变过来。比如县官张三改名为王二麻子,其情妇的称号就会自动改为王二麻子的情妇。嗯。
|
||||
|
||||
MySQL对此一直持观望态度,它允许使用外键,但是为了完整性检验的目的,在除了InnoDB表类型之外的所有表类型中都忽略了这个功能。这可能有些怪异,实际上却非常正常:对于数据库的所有外键的每次插入、更新和删除后,进行完整性检查是一个耗费时间和资源的过程,它可能影响性能,特别是当处理复杂的或者是缠绕的连接树时。因而,用户可以在表的基础上,选择适合于特定需求的最好结合。。
|
||||
|
||||
所以,如果需要更好的性能,并且不需要完整性检查,可以选择使用MyISAM表类型,如果想要在MySQL中根据参照完整性来建立表并且希望在此基础上保持良好的性能,最好选择表结构为innoDB类型。
|
||||
|
||||
**MySQL创建外键语法:**
|
||||
|
||||
创建外键的语法是这样的:FOREIGN KEY (当前表的字段名)… REFERENCES 参照表 (参照表的字段名)
|
||||
|
||||
foreign key (emp_id) references employees (id); 的意思就是说当前表的emp_id字段是以employees的id字段为外键的。
|
||||
|
||||
注意事项:
|
||||
|
||||
* 一旦建立外键,MySQL只允许向当前表中加入**参照表中已有的数据列**。比如说贪官表里有“王二麻子”,那么在情妇表只才能有“王二麻子的情妇”。也就是说只有确认一个人是贪官了,才能把其情妇信息列入此表中,否则是不行滴。
|
||||
* 关系中的所有表必须**是innoDB表**,在非InnoDB表中,MySQL将会忽略FOREIGN KEY…REFERENCES修饰符。
|
||||
* 用于外键关系的字段必须在所有的参照表中进行**明确**地索引,InnoDB不能自动地创建索引。
|
||||
* 在外键关系中,字段的数据类型必须相似,这对于大小和符号都必须匹配的整数类型尤其重要。
|
||||
* 即使表存在外键约束,MySQL还允许我们删除表,并且不会产生错误(即使这样做可能会破坏更早创建的外键)
|
||||
|
||||
**删除外键方法:**
|
||||
|
||||
long long ago,人们只能通过删除表来删除外键。不过现在MySQL(在4.0.13及更高版本中)提供了一种从表中删除外键比较缓和的方法,缓和与否不太清楚,但是至少不再那么无耻。
|
||||
|
||||
ALTER TABLE table-name DROP FOREIGN KEY key-id;
|
||||
|
||||
这里有一个概念,这个外键的id是啥玩意?我们可以通过SHOW CREATE TABLE 命令来获得key-id的值。日后我们详细讨论这些内容,大家可以自行演示。
|
||||
/*
|
||||
显示建表结构语句,key-id为payroll_ibfk_1
|
||||
*/
|
||||
show create table payroll \G
|
||||
/*
|
||||
*************************** 1. row ***************************
|
||||
Table: payroll
|
||||
Create Table: CREATE TABLE `payroll` (
|
||||
`id` int(5) NOT NULL,
|
||||
`emp_id` int(5) NOT NULL,
|
||||
`name` varchar(8) NOT NULL,
|
||||
`payroll` float(4,2) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `emp_id` (`emp_id`),
|
||||
CONSTRAINT `payroll_ibfk_1` FOREIGN KEY (`emp_id`) REFERENCES `employees` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||
1 row in set (0.00 sec)
|
||||
|
||||
*/
|
||||
|
||||
===== 自动键更新和删除: =====
|
||||
|
||||
外键可以保证**新插入**的记录的完整性(对于**含有外键**的表而言)。但是,如果在REFERENCES从句中从已命名的表删除记录会怎样?在使用同样的值作为外键的辅助表中会发生什么?
|
||||
很明显,__那些记录也应该被删除,否则在数据库中就会有很多无意义的孤立记录__。MySQL可能通过向FOREIGN KEY…REFERENCES 修饰符添加一个ON DELETE或ON UPDATE子句简化任务,它告诉了数据库在这种情况如何处理孤立任务。
|
||||
关键字 含义
|
||||
CASCADE 删除包含与已删除键值有参照关系的所有记录
|
||||
SET NULL 修改包含与已删除键值有参照关系的所有记录,使用NULL值替换(只能用于已标记为NOT NULL的字段)
|
||||
RESTRICT 拒绝删除要求,直到使用删除键值的辅助表被手工删除,并且没有参照时(这是默认设置,也是最安全的设置)
|
||||
NO ACTION 啥也不做
|
||||
|
||||
请注意,通过 ON UPDATE 和ON DELETE规则,设置MySQL能够实现自动操作时,如果键的关系没有设置好,可能会导致严重的数据破坏。例如,如果一系列的表通过外键关系和ON DELETE CASCADE 规则连接时,任意一个主表的变化都会导致甚至只和原始删除有一些将要联系的记录在没有警告的情况下被删除。所以,我们在操作之前还是要检查这些规则的,操作之后还要再次检查。
|
||||
|
||||
文章作者:simaopig
|
||||
本文地址:http://www.xiaoxiaozi.com/2009/07/12/1158/
|
||||
版权所有 © 转载时必须以链接形式注明作者和原始出处!
|
||||
|
||||
50
Zim/Programme/python/sql/浅谈MySQL外键/mysql创建外键关联.txt
Normal file
50
Zim/Programme/python/sql/浅谈MySQL外键/mysql创建外键关联.txt
Normal file
@@ -0,0 +1,50 @@
|
||||
Content-Type: text/x-zim-wiki
|
||||
Wiki-Format: zim 0.4
|
||||
Creation-Date: 2011-10-17T11:09:59+08:00
|
||||
|
||||
====== mysql创建外键关联 ======
|
||||
Created Monday 17 October 2011
|
||||
http://eternal1025.iteye.com/blog/425311
|
||||
|
||||
**参照完整性**(Referentialintegrity)是数据库设计中一个重要的概念。在系统不同的列表中,当数据库所有参照合法或非合法关联时都会涉及到参照完整性。当参照完整性存在时,任何与不存在记录的关联将变得无效化,由此可防止用户出现各种错误,从而提供更为准确和实用的数据库。
|
||||
|
||||
参照完整性通常通过**外键**(foreign key)的使用而被广泛应用。长久以来,流行工具开源RDBMSMySQL并没有支持外键,原因是这种支持将会降低RDBMS的速度和性能。然而,由于很多用户对参照完整性的优点倍感兴趣,最近MySQL的不同版本都通过新InnoDB列表引擎支持外键。由此,在数据库组成的列表中保持参照完整性将变得非常简单。
|
||||
|
||||
为了建立两个MySQL表之间的一个外键关系,必须满足以下三种情况:
|
||||
|
||||
* 两个表必须是InnoDB表类型。
|
||||
* 使用在外键关系的域必须为索引型(Index)。
|
||||
* 使用在外键关系的域必须与数据类型相似。
|
||||
|
||||
例子是理解以上要点的最好方法,新建一个parts的表,cpu字段用来存放所有的cpu配件型号,再新建一个pc的表,其中的cpumodel字段用来存放pc机中的cpu型号,显然,cpumodel字段中的所有记录应该存在于parts表中。
|
||||
mysql> create table parts(
|
||||
-> cpu char(20) not null,
|
||||
-> index(cpu)
|
||||
-> )engine=innodb;
|
||||
Query OK, 0 rows affected (0.01 sec)
|
||||
|
||||
mysql> create table pc(
|
||||
-> cpumodel char(20) not null,
|
||||
-> index(cpumodel),
|
||||
-> foreign key(cpumodel) references parts(cpu)
|
||||
-> )engine=innodb;
|
||||
Query OK, 0 rows affected (0.01 sec)
|
||||
|
||||
注意:对于非InnoDB表, FOREIGN KEY 语句将被忽略。对parts表添加数据1,2,3,接着对pc表进行测试,满足条件的 1 可以顺利insert进去,而不符合条件的字符 5 在insert表的时候,出现外键约束性错误,这正是我们想要的结果
|
||||
|
||||
|
||||
mysql> insert into parts values('1'),('2'),('3');
|
||||
Query OK, 3 rows affected (0.00 sec)
|
||||
Records: 3 Duplicates: 0 Warnings: 0
|
||||
|
||||
mysql> insert into pc values('1');
|
||||
Query OK, 1 row affected (0.01 sec)
|
||||
|
||||
|
||||
mysql> insert into pc values('5');
|
||||
ERROR 1452 (23000): Cannot add or update a child row: a foreign
|
||||
key constraint fails (`Orange/pc`, CONSTRAINT `pc_ibfk_1` FOREIGN KEY
|
||||
(`cpumodel`) REFERENCES `parts` (`cpu`))
|
||||
|
||||
|
||||
如以上例子解释的,外键在捉摸数据入口错误上起着重要的作用,由此可建立更为强健更加集成的数据库。另一方面值得提到的是,执行外键核实是内部资料处理的过程,且不同表之间指定复杂的内部关系可以导致数据库的性能下降。所以,在参照完整性与性能考虑之间找到平衡点相当重要,而使用外键就是能够确保性能与稳健之间的最优结合。 我期望本期的有关外键的介绍对你有所好处,你将会在下回的MySQL数据库设计中感受到外键的好处。编程快乐!
|
||||
69
Zim/Programme/python/sql/浅谈MySQL外键/在MySQL中使用外键.txt
Normal file
69
Zim/Programme/python/sql/浅谈MySQL外键/在MySQL中使用外键.txt
Normal file
@@ -0,0 +1,69 @@
|
||||
Content-Type: text/x-zim-wiki
|
||||
Wiki-Format: zim 0.4
|
||||
Creation-Date: 2011-10-17T11:16:07+08:00
|
||||
|
||||
====== 在MySQL中使用外键 ======
|
||||
Created Monday 17 October 2011
|
||||
http://msq.iteye.com/blog/47610
|
||||
昨晚用Mysql建外键约束,始终没有成功,今天找到这个,原来只有InnoDB类型的表才可以使用外键.
|
||||
|
||||
只有InnoDB类型的表才可以使用外键
|
||||
|
||||
CREATE TABLE person (
|
||||
id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
name CHAR(60) NOT NULL,
|
||||
PRIMARY KEY (id)
|
||||
)type=innoDB;
|
||||
|
||||
CREATE TABLE shirt (
|
||||
id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
style ENUM('t-shirt', 'polo', 'dress') NOT NULL,
|
||||
color ENUM('red', 'blue', 'orange', 'white', 'black') NOT NULL,
|
||||
owner SMALLINT UNSIGNED NOT NULL,
|
||||
FOREIGN KEY (owner) REFERENCES PERSON(id)
|
||||
ON DELETE CASCADE
|
||||
ON UPDATE CASCADE,
|
||||
PRIMARY KEY (id)
|
||||
)type=innoDB;
|
||||
|
||||
然后打开MySQL Administrator终于看到 FOREIGN KEY有东西了,尝试手工删除后再用MySQL Administrator建立,成功:)
|
||||
|
||||
INSERT INTO person VALUES (NULL, 'Antonio Paz');
|
||||
|
||||
SELECT @last := LAST_INSERT_ID();
|
||||
|
||||
INSERT INTO shirt VALUES
|
||||
(NULL, 'polo', 'blue', @last),
|
||||
(NULL, 'dress', 'white', @last),
|
||||
(NULL, 't-shirt', 'blue', @last);
|
||||
|
||||
INSERT INTO person VALUES (NULL, 'Lilliana Angelovska');
|
||||
|
||||
SELECT @last := LAST_INSERT_ID();
|
||||
|
||||
INSERT INTO shirt VALUES
|
||||
(NULL, 'dress', 'orange', @last),
|
||||
(NULL, 'polo', 'red', @last),
|
||||
(NULL, 'dress', 'blue', @last),
|
||||
(NULL, 't-shirt', 'white', @last);
|
||||
|
||||
SELECT * FROM person;
|
||||
|
||||
SELECT * FROM shirt;
|
||||
|
||||
测试UPDATE关联
|
||||
UPDATE PERSON SET id=3 WHERE id=1;
|
||||
SELECT * FROM shirt;
|
||||
|
||||
测试DELETE关键
|
||||
DELETE FROM PERSON WHERE id=3;
|
||||
SELECT * FROM shirt;
|
||||
|
||||
看到有文章简单使用owner SMALLINT UNSIGNED NOT NULL REFERENCES person(id),进行连接,但这样的连接好像没任何意义,担看到“MySQL 3.23.7-alpha手册”有这样一句话“一些应用程序要求他们存在”或者“插入强制约束”、“级联删除”、“级联更新”这些特性是在MySQL甘个版本中才有吧
|
||||
|
||||
还有有文章说要建立INDEX (owner) 才可以,但我经测试并不需要,这可能是和MYSQL版本不同有关,我用的是MySQL4.1
|
||||
|
||||
PS.查看Mysql手册才知道从MySQL 4.1.2开始会自动建立这个INDEX (owner)
|
||||
|
||||
参考:
|
||||
http://dev.mysql.com/doc/mysql/en/innodb-foreign-key-constraints.html
|
||||
Reference in New Issue
Block a user