GRANT
和REVOKE
句法
GRANT priv_type [(column_list)] [, priv_type [(column_list)] ...] ON {tbl_name | * | *.* | db_name.*} TO user_name [IDENTIFIED BY 'password'] [, user_name [IDENTIFIED BY 'password'] ...] [WITH GRANT OPTION] REVOKE priv_type [(column_list)] [, priv_type [(column_list)] ...] ON {tbl_name | * | *.* | db_name.*} FROM user_name [, user_name ...]
GRANT
在MySQL 3.22.11或以后版本中实现。对于更早MySQL版本,GRANT
语句不做任何事情。
GRANT
和REVOKE
命令允许系统主管在4个权限级别上授权和撤回赋予MySQL用户的权利:
-
全局级别
-
全局权限作用于一个给定服务器上的所有数据库。这些权限存储在
mysql.user
表中。
数据库级别
-
数据库权限作用于一个给定数据库的所有表。这些权限存储在
mysql.db
和mysql.host
表中。
表级别
-
表权限作用于一个给定表的所有列。这些权限存储在
mysql.tables_priv
表中。
列级别
-
列权限作用于在一个给定表的单个列。这些权限存储在
mysql.columns_priv
表中。
对于GRANT
如何工作的例子,见6.11 为MySQL增加新的用户权限。
对于GRANT
和REVOKE
语句,priv_type
可以指定下列的任何一个:
ALL PRIVILEGES FILE RELOAD ALTER INDEX SELECT CREATE INSERT SHUTDOWN DELETE PROCESS UPDATE DROP REFERENCES USAGE
ALL
是ALL PRIVILEGES
的一个同义词,REFERENCES
还没被实现,USAGE
当前是“没有权限”的一个同义词。它能用在你想要创建一个没有权限用户的时候。
为了从一个用户撤回grant的权限,使用GRANT OPTION
的一个priv_type
值:
REVOKE GRANT OPTION ON ... FROM ...;
对于表,你能指定的唯一priv_type
值是SELECT
、INSERT
、UPDATE
、DELETE
、CREATE
、DROP
、GRANT
、INDEX
和ALTER
。
对于列,你能指定的唯一priv_type
值是(即,当你使用一个column_list
子句时)是SELECT
、INSERT
和UPDATE
。
你能通过使用ON *.*
语法设置全局权限,你能通过使用ON db_name.*
语法设置数据库权限。如果你指定ON *
并且你有一个当前数据库,你将为该数据库设置权限。(警告:如果你指定ON *
而你没有一个当前数据库,你将影响全局权限!)
为了容纳对任意主机的用户授予的权利,MySQL支持以user@host
格式指定user_name
值。如果你想要指定一个特殊字符的一个user
字符串(例如“-”),或一个包含特殊字符或通配符的host
字符串(例如“%”),你可以用括号括起能用户或主机名字 (例如,'test-user'@'test-hostname'
)。
你能在主机名中指定通配符。例如,user@"%.loc.gov"
适用于在loc.gov
域中任何主机的user
,并且user@"144.155.166.%"
适用于在144.155.166
类 C 子网中任何主机的user
。
简单形式的user
是user@"%"
的一个同义词。注意:如果你允许匿名用户连接MySQL服务器(它是缺省的),你也应该增加所有本地用户如user@localhost
,因为否则,当用户试图从本地机器上登录到MySQL服务器时,对于mysql.user
表中的本地主机的匿名用户条目将被使用!匿名用户通过插入有User=''
的条目到mysql.user
表中来定义。通过执行这个查询,你可以检验它是否作用于你:
mysql> SELECT Host,User FROM mysql.user WHERE User='';
目前,GRANT
仅支持最长60个字符的主机、表、数据库和列名。一个用户名字能最多到16个字符。
对与一个表或列的权限是由4个权限级别的逻辑或形成的。例如,如果mysql.user
表指定一个用户有一个全局select权限,它不能被数据库、表或列的一个条目否认。
对于一个列的权限能如下计算:
global privileges OR (database privileges AND host privileges) OR table privileges OR column privileges
在大多数情况下,你只授予用户一个权限级别上的权限,因此现实通常不象上面所说的那样复杂。:) 权限检查过程的细节在6 MySQL 存取权限系统中给出。
如果你为一个在mysql.user
表中不存在的用户/主机名组合授权,一个条目被增加并且保留直到用一个DELETE
命令删除。换句话说,GRANT
可以创建user
表的条目,但是REVOKE
将不删除;你必须明确地使用DELETE
删除.
在MySQL 3.22.12或以后,如果创建一个新用户或如果你有全局授予权限,用户的口令将被设置为由IDENTIFIED BY
子句指定的口令,如果给出一个。如果用户已经有了一个口令,它被一个新的代替。
警告:如果你创造一个新用户但是不指定一个IDENTIFIED BY
子句,用户没有口令。这是不安全的。
口令也能用SET PASSWORD
命令设置。见7.25 SET OPTION
句法。
如果你为一个数据库授权,如果需要在mysql.db
表中创建一个条目。当所有为数据库的授权用REVOKE
删除时,这个条目被删除。
如果一个用户没有在一个表上的任何权限,当用户请求一系列表时,表不被显示(例如,用一个SHOW TABLES
语句)。
WITH GRANT OPTION
子句给与用户有授予其他用户在指定的权限水平上的任何权限的能力。你应该谨慎对待你授予他grant权限的用户,因为具有不同权限的两个用户也许能合并权限!
你不能授予其他用户你自己不具备的权限; agree权限允许你放弃你仅仅拥有的那些权限。
要知道,当你将一个特定权限级别上的grant授予其他用户,用户已经拥有(或在未来被授予!)的在该级别上的任何权限也可由该用户授权。假定你授权一个用户在一个数据库上的insert权限,那么如果你授权在数据库上select权限并且指定WITH GRANT OPTION
,用户能不仅放弃select权限,还有insert。如果你授权用户在数据库上的update权限,用户能放弃insert、select和update。
你不应该将alter权限授予一个一般用户。如果你这样做,用户可以通过重命名表试图颠覆权限系统!
注意,如果你正在使用即使一个用户的表或列的权限,服务器要检查所有用户的表和列权限并且这将使MySQL慢下来一点。
当mysqld
启动时,所有的权限被读入存储器。数据库、表和列权限马上生效,而用户级权限在下一次用户连接时生效。你用GRANT
或REVOKE
对受权表执行的更改立即被服务器知晓。如果你手工修改授权表(使用INSERT
、UPDATE等等),你应该执行一个FLUSH PRIVILEGES
语句或运行mysqladmin flush-privileges
告诉服务器再次装载授权表。见6.9 权限变化何时生效。
ANSI SQL版本的GRANT
与MySQL版本之间的最大差别:
- ANSI SQL 没有全局或数据库级别权限,并且 ANSI SQL 不支持所有MySQL支持的权限。
- 当你在 ANSI SQL 抛弃一张表时,表的所有权限均被撤消。如果你在 ANSI SQL 撤销权限,所有基于该权限的授权也被也被撤消。在MySQL中,权限只能用明确的
REVOKE
命令或操作MySQL授权表抛弃。
7.27 CREATE INDEX
句法
CREATE [UNIQUE] INDEX index_name ON tbl_name (col_name[(length)],... )
CREATE INDEX
语句在MySQL版本 3.22 以前不做任何事情。在 3.22 或以后版本中,CREATE INDEX
被映射到一个ALTER TABLE
语句来创建索引。见7.8 ALTER TABLE
句法。
通常,你在用CREATE TABLE
创建表本身时创建表的所有索引。见7.7 CREATE TABLE
句法。CREATE INDEX
允许你把索引加到现有表中。
一个(col1,col2,...)
形式的列表创造一个多列索引。索引值有给定列的值串联而成。
对于CHAR
和VARCHAR
列,索引可以只用一个列的部分来创建,使用col_name(length)
句法。(在BLOB
和TEXT
列上需要长度)。下面显示的语句使用name
列的头10个字符创建一个索引:
mysql> CREATE INDEX part_of_name ON customer (name(10));
因为大多数名字通常在头10个字符不同,这个索引应该不比从整个name
列的创建的索引慢多少。另外,在索引使用部分的列能使这个索引成为更小的文件大部分, 它能保存很多磁盘空格并且可能也加快INSERT
操作!
注意,如果你正在使用MySQL版本 3.23.2 或更新并且正在使用MyISAM
桌子类型,你只能在可以有NULL
值的列或一个BLOB
/TEXT
列上增加一个索引,
关于MySQL如何使用索引的更多信息,见10.4 MySQL索引的使用。
7.28 DROP INDEX
句法
DROP INDEX index_name ON tbl_name
DROP INDEX
从tbl_name
表抛弃名为index_name
的索引。DROP INDEX
在MySQL 3.22 以前的版本中不做任何事情。在 3.22 或以后,DROP INDEX
被映射到一个ALTER TABLE
语句来抛弃索引。见7.8 ALTER TABLE
句法。
7.29 注释句法
MySQL服务器支持# to end of line
、-- to end of line
和/* in-line or multiple-line */
注释风格:
mysql> select 1+1; # This comment continues to the end of line mysql> select 1+1; -- This comment continues to the end of line mysql> select 1 /* this is an in-line comment */ + 1; mysql> select 1+ /* this is a multiple-line comment */ 1;
注意--
注释风格要求你在--
以后至少有一个空格!
尽管服务者理解刚才描述的注释句法,mysql
客户分析/* ... */
注释的方式上有一些限制:
- 单引号和双引号字符被用来标志一个括起来的字符串的开始,即使在一篇注释内。如果引号在主室内没被第2个引号匹配,分析器不知道注释已经结束。如果你正在交互式运行
mysql
,你能告知有些混乱,因为提示符从mysql>
变为'>
或">
。 - 一个分号被用来指出当前的SQL语句结束并且跟随它的任何东西表示下一行的开始。
当你交互式运行mysql
时和当你把命令放在一个文件中并用mysql < some-file
告诉mysql
从那个文件读它的输入时,这些限制都适用。
MySQL不支持‘--’的ANSI SQL注释风格。见5.4.7 ‘--’作为一篇注释的开始。
7.30 CREATE FUNCTION/DROP FUNCTION
句法
CREATE [AGGREGATE] FUNCTION function_name RETURNS {STRING|REAL|INTEGER} SONAME shared_library_name DROP FUNCTION function_name
一个用户可定义函数(UDF)是用一个像MySQL的原生(内置)函数如ABS()
和CONCAT()
的新函数来扩展MySQL的方法。
AGGREGATE
是MySQL 3.23的一个新选项。一个AGGREGATE
函数功能就像一个原生MySQL GROUP
函数如SUM
或COUNT()
。
CREATE FUNCTION
在mysql.func
系统表中保存函数名、类型和共享库名。你必须对mysql
数据库有insert和delete权限以创建和抛弃函数。
所有活跃的函数在每次服务器启动时被重新装载,除非你使用--skip-grant-tables
选项启动mysqld
,在这种情况下,UDF初始化被跳过并且UDF是无法获得的。(一个活跃函数是一个已经用CREATE FUNCTION
装载并且没用DROP FUNCTION
删除的函数。)
关于编写用户可定义函数的指令,见14 为MySQL增加新函数。对于UDF的工作机制,函数必须用 C 或 C++ 编写,你的操作系统必须支持动态装载并且你必须动态编译了mysqld
(不是静态)。
7.31 MySQL对保留词很挑剔吗?
一个常见的问题源自于试图使用MySQL内置的数据类型或函数名同名的列来创建数据库表,例如TIMESTAMP
或GROUP
。你允许这样做(例如,ABS
是一个允许的列名),但是当使用其名字也是列名的函数时,在一个函数名和“ ( ”之间不允许白空。
下列词明确地在MySQL中被保留。他们的大多数被 ANSI SQL92 禁止作为列或表名(例如,group
)。一些被保留因为MySQL需要他们并且正在(当前)使用一个yacc
分析器:
action | add | aggregate | all |
alter | after | and | as |
asc | avg | avg_row_length | auto_increment |
between | bigint | bit | binary |
blob | bool | both | by |
cascade | case | char | character |
change | check | checksum | column |
columns | comment | constraint | create |
cross | current_date | current_time | current_timestamp |
data | database | databases | date |
datetime | day | day_hour | day_minute |
day_second | dayofmonth | dayofweek | dayofyear |
dec | decimal | default | delayed |
delay_key_write | delete | desc | describe |
distinct | distinctrow | double | drop |
end | else | escape | escaped |
enclosed | enum | explain | exists |
fields | file | first | float |
float4 | float8 | flush | foreign |
from | for | full | function |
global | grant | grants | group |
having | heap | high_priority | hour |
hour_minute | hour_second | hosts | identified |
ignore | in | index | infile |
inner | insert | insert_id | int |
integer | interval | int1 | int2 |
int3 | int4 | int8 | into |
if | is | isam | join |
key | keys | kill | last_insert_id |
leading | left | length | like |
lines | limit | load | local |
lock | logs | long | longblob |
longtext | low_priority | max | max_rows |
match | mediumblob | mediumtext | mediumint |
middleint | min_rows | minute | minute_second |
modify | month | monthname | myisam |
natural | numeric | no | not |
null | on | optimize | option |
optionally | or | order | outer |
outfile | pack_keys | partial | password |
precision | primary | procedure | process |
processlist | privileges | read | real |
references | reload | regexp | rename |
replace | restrict | returns | revoke |
rlike | row | rows | second |
select | set | show | shutdown |
smallint | soname | sql_big_tables | sql_big_selects |
sql_low_priority_updates | sql_log_off | sql_log_update | sql_select_limit |
sql_small_result | sql_big_result | sql_warnings | straight_join |
starting | status | string | table |
tables | temporary | terminated | text |
then | time | timestamp | tinyblob |
tinytext | tinyint | trailing | to |
type | use | using | unique |
unlock | unsigned | update | usage |
values | varchar | variables | varying |
varbinary | with | write | when |
where | year | year_month | zerofill |
下列符号(来自上表)被ANSI SQL禁止但是被MySQL允许作为列/表名。这是因为这些名字的一些是很自然的名字并且很多人已经使用了他们。
-
ACTION
-
BIT
-
DATE
-
ENUM
-
NO
-
TEXT
-
TIME
-
TIMESTAMP