首页博客SEMCASE论坛网站地图标签列表

数据库优化  { 分类归档 }

2006-07-31

转:储过程编写经验和优化措施

一、适合读者对象:数据库开发程序员,数据库的数据量很多,涉及到对SP(存储过程)的优化的项目开发人员,对数据库有浓厚兴趣的人。  

(阅读全文…)

No Tags

2006-07-16

转:谈数据仓库投资回报

企业对于任何行动都想知道一件事情:“投资回报率 (ROI) 是多少?” 投资的每一元钱都应持之有据,购入的任何技术都应提供积极有形的成效。 企业追求ROI的过程,也是自身需求由模糊到清晰的过程。 数据仓库市场早期发展并不理想,如今市场已日渐成熟,许多企业已经开始受益于投资的成果。但毕竟建立数据仓库是牵扯企业业务、管理、IT系统等多方面“大工程”,企业要真正发挥其效益,如若没有通过一定的评估手段,明确投资回报结果,数据仓库的价值或许难以被真正获得。 CIO:给我评估方法 投资回报是投资所获得或节省的部分(即项目收益)除以投资所耗费的部分(即项目成本)。

(阅读全文…)

转:服务器技术与数据仓库

从体系结构来看,目前广泛应用于关键业务领域的商用服务器大体可以分为三类,即对称多处理器结构(SMP:Symmetric Multi-Processor),非一致存储访问结构(NUMA:Non-Uniform Memory Access) 以及海量并行处理结构(MPP:Massive Parallel Processing)。

(阅读全文…)

如何让你的SQL运行得更快!

一、不合理的索引设计 —-例:表record有620000行,试看在不同的索引下,下面几个 SQL的运行情况: —- 1.在date上建有一非个群集索引 select count(*) from record where date > ′19991201′ and date < ′19991214′and amount > 2000 (25秒) select date,sum(amount) from record group by date (55秒) select count(*) from record where date > ′19990901′ and place in (′BJ′,′SH′) (27秒) —- 分析: —-date上有大量的重复值,在非群集索引下,数据在物理上随机存放在数据页上,在 范围查找时,必须执行一次表扫描才能找到这一范围内的全部行。 —- 2.在date上的一个群集索引 select count(*) from record where date > ′19991201′ and date < ′19991214′ and amount > 2000 (14秒) select date,sum(amount) from record group by date (28秒) select count(*) from record where date > ′19990901′ and place in (′BJ′,′SH′)(14秒) —- 分析: —- 在群集索引下,数据在物理上按顺序在数据页上,重复值也排列在一起,因而在范 围查找时,可以先找到这个范围的起末点,且只在这个范围内扫描数据页,避免了大范 围扫描,提高了查询速度。 —- 3.在place,date,amount上的组合索引 select count(*) from record where date > ′19991201′ and date < ′19991214′ and amount > 2000 (26秒) select date,sum(amount) from record group by date (27秒) select count(*) from record where date > ′19990901′ and place in (′BJ′, ′SH′)(< 1秒) —- 分析: —- 这是一个不很合理的组合索引,因为它的前导列是place,第一和第二条SQL没有引 用place,因此也没有利用上索引;第三个SQL使用了place,且引用的所有列都包含在组 合索引中,形成了索引覆盖,所以它的速度是非常快的。 —- 4.在date,place,amount上的组合索引 select count(*) from record where date > ′19991201′ and date < ′19991214′ and amount > 2000(< 1秒) select date,sum(amount) from record group by date (11秒) select count(*) from record where date > ′19990901′ and place in (′BJ′,′SH′)(< 1秒) —- 分析: —- 这是一个合理的组合索引。它将date作为前导列,使每个SQL都可以利用索引,并 且在第一和第三个SQL中形成了索引覆盖,因而性能达到了最优。 —- 5.总结: —- 缺省情况下建立的索引是非群集索引,但有时它并不是最佳的;合理的索引设计要 建立在对各种查询的分析和预测上。一般来说: —- ①.有大量重复值、且经常有范围查询 (between, >,< ,>=,< =)和order by 、group by发生的列,可考虑建立群集索引; —- ②.经常同时存取多列,且每列都含有重复值可考虑建立组合索引; —- ③.组合索引要尽量使关键查询形成索引覆盖,其前导列一定是使用最频繁的列。

(阅读全文…)

数据库的查询优化技术

数据库系统是管理信息系统的核心,基于数据库的联机事务处理(OLTP)以及联机分析处理(OLAP)是银行、企业、政府等部门最为重要的计算机应用之一。 从大多数系统的应用实例来看,查询操作在各种数据库操作中所占据的比重最大,而查询操作所基于的SELECT语句在SQL语句中又是代价最大的语句。 举例来说,如果数据的量积累到一定的程度,比如一个银行的账户数据库表信息积累到上百万甚至上千万条记录,全表扫描一次往往需要数十分钟,甚至数小时。 如果采用比全表扫描更好的查询策略,往往可以使查询时间降为几分钟,由此可见查询优化技术的重要性。

(阅读全文…)

2006-07-02

MYSQL 5.0 新特性教程 存储过程

Error Handling 异常处理 我们现在要讲的是异常处理 1. Sample Problem: Log Of Failures 问题样例:故障记录    当INSERT失败时,我希望能将其记录在日志文件中我们用来展示出错处理的问题样例是很 普通的。 我希望得到错误的记录。 当INSERT失败时,我想在另一个文件中记下这些错误的 信息, 例如出错时间,出错原因等。 我对插入特别感兴趣的原因是它将违反外键关联的约束 2. Sample Problem: Log Of Failures (2) mysql> CREATE TABLE t2 s1 INT, PRIMARY KEY (s1)) engine=innodb; // mysql> CREATE TABLE t3 (s1 INT, KEY (s1), FOREIGN KEY (s1) REFERENCES t2 (s1)) engine=innodb; // mysql> INSERT INTO t3 VALUES (5); // … ERROR 1216 (23000): Cannot add or update a child row: a foreign key constraint fails(这里显示的是系统的出错信息)   我开始要创建一个主键表,以及一个外键表。 我们使用的是InnoDB,因此外键关联检查是打 开的。 然后当我向外键表中插入非主键表中的值时,动作将会失败。 当然这种条件下可以很 快找到错误号1216。 3. Sample Problem: Log Of Failures CREATE TABLE error_log (error_message CHAR(80)) //  下一步就是建立一个在做插入动作出错时存储错误的表。 4. Sample Problem: Log Of Errors CREATE PROCEDURE p22 (parameter1 INT) BEGIN DECLARE EXIT HANDLER FOR 1216 INSERT INTO error_log VALUES (CONCAT(’Time: ‘,current_date, ‘. Foreign Key Reference Failure For Value = ‘,parameter1)); INSERT INTO t3 VALUES (parameter1); END; //  上面就是我们的程序。这里的第一个语句DECLARE EXIT HANDLER是用来处理异常的。 意思是如果错误1215发生了,这个程序将会在错误记录表中插入一行。 EXIT意思是当动作成功提交后退出这个复合语句。 5. Sample Problem: Log Of Errors CALL p22 (5) //   调用这个存储过程会失败,这很正常,因为5值并没有在主键表中出现。 但是没有错误信息 返回因为出错处理已经包含在过程中了。 t3表中没有增加任何东西,但是error_log表中记录 下了一些信息,这就告诉我们INSERT into table t3动作失败。 DECLARE HANDLER syntax 声明异常处理的语法 DECLARE { EXIT | CONTINUE } HANDLER FOR { error-number | { SQLSTATE error-string } | condition } SQL statement    上面就是错误处理的用法,也就是一段当程序出错后自动触发的代码。 MySQL允许两种处理器,一种是EXIT处理,我们刚才所用的就是这种。 另一种就是我们将要演示的,CONTINUE处理,它跟EXIT处理类似,不同在于它执行后,原主程序仍然继续运行,那么这个复合语句就没有出口了。 1. DECLARE CONTINUE HANDLER example CONTINUE处理例子 CREATE TABLE t4 (s1 int,primary key(s1)); // CREATE PROCEDURE p23 () BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE ‘23000′ SET @x2 = 1; SET @x = 1; INSERT INTO t4 VALUES (1); SET @x = 2; INSERT INTO t4 VALUES (1); SET @x = 3; END; //   这是MySQL参考手册上的CONTINUE处理的例子,这个例子十分好,所以我把它拷贝到这里。   通过这个例子我们可以看出CONTINUE处理是如何工作的。 2. DECLARE CONTINUE HANDLER声明CONTINUE异常处理 CREATE TABLE t4 (s1 int,primary key(s1));// CREATE PROCEDURE p23 () BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE ‘23000′ SET @x2 = 1; <– SET @x = 1; INSERT INTO t4 VALUES (1); SET @x = 2; INSERT INTO t4 VALUES (1); SET @x = 3; END;//   这次我将为SQLSTATE值定义一个处理程序。还记得前面我们使用的MySQL错误代码1216吗? 事实上这里的23000SQLSTATE是更常用的,当外键约束出错或主键约束出错就被调用了。 3. DECLARE CONTINUE HANDLER CREATE TABLE t4 (s1 int,primary key(s1));// CREATE PROCEDURE p23 () BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE ‘23000′ SET @x2 = 1; SET @x = 1; <– INSERT INTO t4 VALUES (1); SET @x = 2; INSERT INTO t4 VALUES (1); SET @x = 3; END; //   这个存储过程的第一个执行的语句是"SET @x = 1"。 4. DECLARE CONTINUE HANDLER example CREATE TABLE t4 (s1 int,primary key(s1));// CREATE PROCEDURE p23 () BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE ‘23000′ SET @x2 = 1; SET @x = 1; INSERT INTO t4 VALUES (1); SET @x = 2; INSERT INTO t4 VALUES (1); <– SET @x = 3; END;//    运行后值1被插入到主键表中。 5. DECLARE CONTINUE HANDLER CREATE TABLE t4 (s1 int,primary key(s1)); // CREATE PROCEDURE p23 () BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE ‘23000′ SET @x2 = 1; SET @x = 1; INSERT INTO t4 VALUES (1); SET @x = 2; <– INSERT INTO t4 VALUES (1); SET @x = 3; END;//    然后@x的值变为2。 6. DECLARE CONTINUE HANDLER example CREATE TABLE t4 (s1 int,primary key(s1));// CREATE PROCEDURE p23 () BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE ‘23000′ SET @x2 = 1; SET @x = 1; INSERT INTO t4 VALUES (1); SET @x = 2; INSERT INTO t4 VALUES (1); <– SET @x = 3; END; //   然后程序尝试再次往主键表中插入数值,但失败了,因为主键有唯一性限制。 7. DECLARE CONTINUE HANDLER example CREATE TABLE t4 (s1 int,primary key(s1));// CREATE PROCEDURE p23 () BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE ‘23000′ SET @x2 = 1; <– SET @x = 1; INSERT INTO t4 VALUES (1); SET @x = 2; INSERT INTO t4 VALUES (1); SET @x = 3; END; //   由于插入失败,错误处理程序被触发,开始进行错误处理。 下一个执行的语句是错误处理的语句,@x2被设为2。 8. DECLARE CONTINUE HANDLER example CREATE TABLE t4 (s1 int,primary key(s1)); // CREATE PROCEDURE p23 () BEGIN DECLARE CONTINUE HANDLER FOR SQLSTATE ‘23000′ SET @x2 = 1; SET @x = 1; INSERT INTO t4 VALUES (1); SET @x = 2; INSERT INTO t4 VALUES (1); SET @x = 3; <– END; //   到这里并没有结束,因为这是CONTINUE异常处理 。所以执行返回到失败的插入语句之后,继续执行将@x设定为3动作。 9. DECLARE CONTINUE HANDLER example mysql> CALL p23() // Query OK, 0 rows affected (0.00 sec) mysql> SELECT @x, @x2// +——+——+ | @x | @x2 | +——+——+ | 3 | 1 | +——+——+ 1 row in set (0.00 sec) 运行过程后我们观察@x的值,很确定的可以知道是3,观察@x2的值,为1。 从这里可以判断程序运行无误,完全按照我们的思路进行。 大家可以花点时间去调整错误处理器,让检查放在语句段的首部,而不是放在可能出现错误的地方,虽然那样看起来程序很紊乱,跳来跳去的感觉。但是这样的代码很安全也很清楚。 1. DECLARE CONDITION CREATE PROCEDURE p24 () BEGIN DECLARE `Constraint Violation` CONDITION FOR SQLSTATE ‘23000′; DECLARE EXIT HANDLER FOR `Constraint Violation` ROLLBACK; START TRANSACTION; INSERT INTO t2 VALUES (1); INSERT INTO t2 VALUES (1); COMMIT; END; //   这是另外一个错误处理的例子,在前面的基础上修改的。事实上你可给SQLSTATE或者错误代码其他的名字,你就可以在处理中使用自己定义的名字了。 下面看它是怎么实现的:我把表t2定义为InnoDB表,所以对这个表的插入操作都会ROLLBACK(回滚),ROLLBACK(回滚事务)也是恰好会发生的。 因为对主键插入两个同样的值会导致SQLSTATE 23000错误发生,这里SQLSTATE 23000是约束错误。 2. DECLARE CONDITION声明条件 CREATE PROCEDURE p24 () BEGIN DECLARE `Constraint Violation` CONDITION FOR SQLSTATE ‘23000′; DECLARE EXIT HANDLER FOR `Constraint Violation` ROLLBACK; START TRANSACTION; INSERT INTO t2 VALUES (1); INSERT INTO t2 VALUES (1); COMMIT; END; //   这个约束错误会导致ROLLBACK(回滚事务)和SQLSTATE 23000错误发生。 3. DECLARE CONDITION mysql> CALL p24()// Query OK, 0 rows affected (0.28 sec) mysql> SELECT * FROM t2// Empty set (0.00 sec)    我们调用这个存储过程看结果是什么,从上面结果我们看到表t2没有插入任何记录。全部事务都回滚了。这正是我们想要的。 4. DECLARE CONDITION mysql> CREATE PROCEDURE p9 () -> BEGIN -> DECLARE EXIT HANDLER FOR NOT FOUND BEGIN END; -> DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN END; -> DECLARE EXIT HANDLER FOR SQLWARNING BEGIN END; -> END; // Query OK, 0 rows affected (0.00 sec) 这里是三个预声明的条件:NOT FOUND (找不到行), SQLEXCEPTION (错误), SQLWARNING (警告或注释)。 因为它们是预声明的,因此不需要声明条件就可以使用。 不过如果你去做这样的声明:"DECLARE SQLEXCEPTION CONDITION …",你将会得到错误信息提示。 Cursors 游标    游标实现功能摘要: DECLARE cursor-name CURSOR FOR SELECT …; OPEN cursor-name; FETCH cursor-name INTO variable [, variable]; CLOSE cursor-name;   现在我们开始着眼游标了。虽然我们的存储过程中的游标语法还并没有完整的实现,但是已经可以完成基本的事务如声明游标,打开游标,从游标里读取,关闭游标。 1. Cursor Example CREATE PROCEDURE p25 (OUT return_val INT) BEGIN DECLARE a,b INT; DECLARE cur_1 CURSOR FOR SELECT s1 FROM t; DECLARE CONTINUE HANDLER FOR NOT FOUND SET b = 1; OPEN cur_1; REPEAT FETCH cur_1 INTO a; UNTIL b = 1 END REPEAT; CLOSE cur_1; SET return_val = a; END;//   我们看一下包含游标的存储过程的新例子。 2. Cursor Example CREATE PROCEDURE p25 (OUT return_val INT) BEGIN DECLARE a,b INT; <– DECLARE cur_1 CURSOR FOR SELECT s1 FROM t; DECLARE CONTINUE HANDLER FOR NOT FOUND SET b = 1; OPEN cur_1; REPEAT FETCH cur_1 INTO a; UNTIL b = 1 END REPEAT; CLOSE cur_1; SET return_val = a; END; //   这个过程开始声明了三个变量。 附带说一下,顺序是十分重要的。 首先要进行变量声明,然后声明条件,随后声明游标,再后面才是声明错误处理器。如果你没有按顺序声明,系统会提示错误信息。 3. Cursor Example CREATE PROCEDURE p25 (OUT return_val INT) BEGIN DECLARE a,b INT; DECLARE cur_1 CURSOR FOR SELECT s1 FROM t; <– DECLARE CONTINUE HANDLER FOR NOT FOUND SET b = 1; OPEN cur_1; REPEAT FETCH cur_1 INTO a; UNTIL b = 1 END REPEAT; CLOSE cur_1; SET return_val = a; END; //   程序第二步声明了游标cur_1,如果你使用过嵌入式SQL的话,就知道这和嵌入式SQL差不多。 4. Cursor Example CREATE PROCEDURE p25 (OUT return_val INT) BEGIN DECLARE a,b INT; DECLARE cur_1 CURSOR FOR SELECT s1 FROM t; DECLARE CONTINUE HANDLER FOR NOT FOUND <– SET b = 1; <– OPEN cur_1; REPEAT FETCH cur_1 INTO a; UNTIL b = 1 END REPEAT; CLOSE cur_1; SET return_val = a; END; //   最后进行的是错误处理器的声明。 这个CONTINUE处理没有引用SQL错误代码和SQLSTATE值。 它使用的是NOT FOUND系统返回值,这和SQLSTATE 02000是一样的。 5. Cursor Example CREATE PROCEDURE p25 (OUT return_val INT) BEGIN DECLARE a,b INT; DECLARE cur_1 CURSOR FOR SELECT s1 FROM t; DECLARE CONTINUE HANDLER FOR NOT FOUND SET b = 1; OPEN cur_1; <– REPEAT FETCH cur_1 INTO a; UNTIL b = 1 END REPEAT; CLOSE cur_1; SET return_val = a; END; //   过程第一个可执行的语句是OPEN cur_1,它与SELECT s1 FROM t语句是关联的,过程将执行SELECT s1 FROM t,返回一个结果集。 6. Cursor Example CREATE PROCEDURE p25 (OUT return_val INT) BEGIN DECLARE a,b INT; DECLARE cur_1 CURSOR FOR SELECT s1 FROM t; DECLARE CONTINUE HANDLER FOR NOT FOUND SET b = 1; OPEN cur_1; REPEAT FETCH cur_1 INTO a; <– UNTIL b = 1 END REPEAT; CLOSE cur_1; SET return_val = a; END; //   这里第一个FETCH语句会获得一行从SELECT产生的结果集中检索出来的值,然而表t中有多行,因此这个语句会被执行多次,当然这是因为语句在循环块内。 7. Cursor Example CREATE PROCEDURE p25 (OUT return_val INT) BEGIN DECLARE a,b INT; DECLARE cur_1 CURSOR FOR SELECT s1 FROM t; DECLARE CONTINUE HANDLER FOR NOT FOUND SET b = 1; <– OPEN cur_1; REPEAT FETCH cur_1 INTO a; UNTIL b = 1 END REPEAT; CLOSE cur_1; SET return_val = a; END; //   最后当MySQL的FETCH没有获得行时,CONTINUE处理被触发,将变量b赋值为1。 8. Cursor Example CREATE PROCEDURE p25 (OUT return_val INT) BEGIN DECLARE a,b INT; DECLARE cur_1 CURSOR FOR SELECT s1 FROM t; DECLARE CONTINUE HANDLER FOR NOT FOUND SET b = 1; OPEN cur_1; REPEAT FETCH cur_1 INTO a; UNTIL b = 1 END REPEAT; CLOSE cur_1; <– SET return_val = a; END; //   到了这一步UNTIL b=1条件就为真,循环结束。 在这里我们可以自己编写代码关闭游标,也可以由系统执行,系统会在复合语句结束时自动关闭游标,但是最好不要太依赖系统的自动关闭行为(译注:这可能跟Java的Gc一样,不可信)。 9. Cursor Example CREATE PROCEDURE p25 (OUT return_val INT) BEGIN DECLARE a,b INT; DECLARE cur_1 CURSOR FOR SELECT s1 FROM t; DECLARE CONTINUE HANDLER FOR NOT FOUND SET b = 1; OPEN cur_1; REPEAT FETCH cur_1 INTO a; UNTIL b = 1 END REPEAT; CLOSE cur_1; SET return_val = a; <– END; //   这个例程中我们为输出参数指派了一个局部变量,这样在过程结束后的结果仍能使用。 10. Cursor Example CREATE PROCEDURE p25 (OUT return_val INT) BEGIN DECLARE a,b INT; DECLARE cur_1 CURSOR FOR SELECT s1 FROM t; DECLARE CONTINUE HANDLER FOR NOT FOUND SET b = 1; OPEN cur_1; REPEAT FETCH cur_1 INTO a; UNTIL b = 1 END REPEAT; CLOSE cur_1; SET return_val = a; END; // mysql> CALL p25(@return_val) // Query OK, 0 rows affected (0.00 sec) mysql> SELECT @return_val// +————-+ | @return_val | +————-+ | 5 | +————-+ 1 row in set (0.00 sec)    上面是过程调用后的结果。 可以看到return_val参数获得了数值5,因为这是表t的最后一行。    由此可以知道游标工作正常,出错处理也工作正常。 Cursor Characteristics 游标的特性    摘要:    READ ONLY只读属性   NOT SCROLLABLE顺序读取   ASENSITIVE敏感   在5.0版的MySQL中,你只可以从游标中取值,不能对其进行更新。 因为游标是(READONLY)只读的。 你可以这样做: FETCH cursor1 INTO variable1; UPDATE t1 SET column1 = ‘value1′ WHERE CURRENT OF cursor1;   游标也是不可以滚动的,只允许逐一读取下一行,不能在结果集中前进或后退。 下面代码就是错误的: FETCH PRIOR cursor1 INTO variable1; FETCH ABSOLUTE 55 cursor1 INTO variable1;    同时也不允许在已打开游标进行操作的表上执行updates事务,因为游标是(ASENSITIVE)敏感的。 因为如果你不阻止update事务,那就不知道结果会变成什么。如果你使用的是InnoDB而不是MyISAM存储引擎的话,结果也会不一样。 Security 安全措施   摘要   Privileges (1) CREATE ROUTINE   Privileges (2) EXECUTE   Privileges (3) GRANT SHOW ROUTINE?   Privileges (4) INVOKERS AND DEFINERS   这里我们要讨论一些关于特权和安全相关的问题。 但因为在MySQL安全措施的功能并没有完全,所以我们不会对其进行过多讨论。 1. Privileges CREATE ROUTINE GRANT CREATE ROUTINE ON database-name . * TO user(s) [WITH GRANT OPTION];    现在用root就可以了    在这里要介绍的特权是CREATE ROUTINE,它不仅同其他特权一样可以创建存储过程和函数,还可以创建视图和表。 Root用户拥有这种特权,同时还有ALTER ROUTINE特权。 2. Privileges EXECUTE GRANT EXECUTE ON p TO peter [WITH GRANT OPTION];   上面的特权是决定你是否可以使用或执行存储过程的特权,过程创建者默认拥有这个特权。 3. Privileges SHOW ROUTINE? GRANT SHOW ROUTINE ON db6.* TO joey [WITH GRANT OPTION];    因为我们已经有控制视图的特权了:GRANT SHOW VIEW。 所以在这个基础上,为了保证兼容,日后可能会添加GRANT SHOW ROUTINE特权。 这样做是不太符合标准的,在写本书的时候,MySQL还没实现这个功能。 4. Privileges Invokers and Definers 特权调用者和定义者 CREATE PROCEDURE p26 () SQL SECURITY INVOKER SELECT COUNT(*) FROM t // CREATE PROCEDURE p27 () SQL SECURITY DEFINER SELECT COUNT(*) FROM t // GRANT INSERT ON db5.* TO peter; //   现在我们测试一下SQL SECURITY子句吧。 Security是我们前面提到的程序特性的一部分。 你root用户,将插入权赋给了peter。然后使用peter登陆进行新的工作,我们看peter可以怎么使用存储过程,注意:peter没有对表t的select权力,只有root用户有。 5. Privileges Invokers and Definers /* Logged on with current_user = peter */使用帐户peter登陆 mysql> CALL p26(); ERROR 1142 (42000): select command denied to user ‘peter’@'localhost’ for table ‘t’ mysql> CALL p27(); +———-+ | COUNT(*) | +———-+ | 1 | +———-+ 1 row in set (0.00 sec)    当peter尝试调用含有调用保密措施的过程p26时会失败。那是因为peter没有对表的select的权力。    但是当petre调用含有定义保密措施的过程时就能成功。 原因是root有select权力,Peter有root的权力,因此过程可以执行。

2006-06-28

mssql CONVERT

SELECT CONVERT(VARCHAR(30),GETDATE(),0) 在函数CONVERT()中你可以使用许多种不同风格的日期和时间格式。 下表显示了所有的格式。 日期和时间的类型: 类型值 标准 输出 0 Default mon dd yyyy hh:miAM 1 USA mm/dd/yy 2 ANSI yy.mm.dd 3 British/French dd/mm/yy 4 German dd.mm.yy 5 Italian dd-mm-yy 6 - dd mon yy 7 - mon dd,yy 8 - hh:mi:ss 9 Default + milliseconds–mon dd yyyy hh:mi:ss:mmmAM(or ) 10 USA mm-dd-yy 11 JAPAN yy/mm/dd 12 ISO yymmdd 13 Europe Default + milliseconds–dd mon yyyy hh:mi:ss:mmm(24h) 14 - hh:mi:ss:mmm(24h) 类型0,9,和13总是返回四位的年。 对其它类型,要显示世纪,把style值加上100。 类型13和14返回24小时时钟的时间。 类型0,7,和13返回的月份用三位字符表示(用Nov代表November). 对表中所列的每一种格式,你可以把类型值加上100来显示有世纪的年(例如,00年将显示为2000年)。 例如,要按日本标准显示日期,包括世纪,你应使用如下的语句: SELECT CONVERT(VARCHAR(30),GETDATE(),111) 在这个例子中,函数CONVERT()把日期格式进行转换,显示为1997/11/30 抽取日期和时间 在许多情况下,你也许只想得到日期和时间的一部分,而不是完整的日期和时间。 为了抽取日期的特定部分,你可以使用函数DATEPART(), 象这样: SELECT name, DATEPART(mm,getDate()) as Month FROM table1 函数DATEPART()的参数是两个变量。第一个变量指定要抽取日期的哪一部分;第二个变量是实际的数据。 在这个例子中,函数DATEPART()抽取月份,因为mm代表月份。 函数DATEPART()的返回值是一个整数。你可以用这个函数抽取日期的各个不同部分, 如下表所示。 日期的各部分及其简写 日期部分 简写 值 year yy 1753–9999 quarter qq 1–4 month mm 1–12 day of year dy 1–366 day dd 1–31 week wk 1–53 weekday dw 1–7(Sunday–Saturday) hour hh 0–23 minute mi 0–59 second ss 0–59 milisecond ms 0–999 函数DATENAME()和函数DATEPART()接收同样的参数。 但是,它的返回值是一个字符串,而不是一个整数。 (如: 2 –>February ) 你也可以用函数DATENAE()来抽取一个星期中的某一天。 下面的这个例子同时抽取一周中的某一天和日期中的月份: SELECT name, DATENAME(dw,getDate())+ ‘-’ + DATENAME(mm,getDate()) as dName FORM table1 结果:( Friday - February) 返回日期和时间范围 SELECT * FROM weblog WHERE entrydate>=”12/25/2000” AND entrydate<”12/26/2000” SELECT * FROM weblog WHERE entrydate LIKE ‘Dec 25 2000%’ 比较日期和时间 函数DATEADD()和DATEDIFF(); DATEDIFF(hh,entrydate,GETDATE()) ; DATEADD(mm,1,firstvisit_date)

2006-06-22

MySQL初学者使用指南(上篇)

一、连接MYSQL 格式:

 mysql -h主机地址 -u用户名 -p用户密码

1、例1:连接到本机上的MYSQL。 首先在打开DOS窗口,然后进入目录 mysqlbin,再键入命令mysql -uroot -p,回车后提示你输密码,如果刚安装好MYSQL,超级用户root是没有密码的,故直接回车即可进入到MYSQL中了,MYSQL的提示符是:mysql>

2、例2:连接到远程主机上的MYSQL。假设远程主机的IP为:110.110.110.110,用户名为root,密码为abcd123。则键入以下命令: mysql -h110.110.110.110 -uroot -pabcd123 (注:u与root可以不用加空格,其它也一样)

3、退出MYSQL命令: exit (回车)

 二、修改密码 格式:

mysqladmin -u用户名 -p旧密码 password 新密码

1、例1:给root加个密码ab12。首先在DOS下进入目录mysqlbin,然后键入以下命令 mysqladmin -uroot -password ab12 注:因为开始时root没有密码,所以-p旧密码一项就可以省略了。

2、例2:再将root的密码改为djg345。 mysqladmin -uroot -pab12 password djg345

三、增加新用户
(注意:和上面不同,下面的因为是MYSQL环境中的命令,所以后面都带一个分号作为命令结束符)
格式:grant select on 数据库.* to 用户名@登录主机 identified by "密码"

例1、增加一个用户test1密码为abc,让他可以在任何主机上登录,并对所有数据库有查询、插入、修改、删除的权限。
首先用以root用户连入MYSQL,然后键入以下命令: grant select,insert,update,delete on *.* to test1@"%" Identified by "abc"; 但例1增加的用户是十分危险的,你想如某个人知道test1的密码,那么他就可以在internet上的任何一台电脑上登录你的mysql数据库并对你的数据可以为所欲为了,解决办法见例2。

例2、增加一个用户test2密码为abc,让他只可以在localhost上登录,并可以对数据库mydb进行查询、插入、修改、删除的操作(localhost指本地主机,即MYSQL数据库所在的那台主机),这样用户即使用知道test2的密码,他也无法从internet上直接访问数据库,只能通过MYSQL主机上的web页来访问了。
grant select,insert,update,delete on mydb.* to test2@localhost identified by "abc"; 如果你不想test2有密码,可以再打一个命令将密码消掉。
grant select,insert,update,delete on mydb.* to test2@localhost identified by "";