MySQL高级

来源:互联网 发布:sqlserver精简版 64位 编辑:程序博客网 时间:2024/05/14 11:44

MySQL高级

2013年10月14日

9:39

 

-------->update user set password=password('new password') where user='root';

change password-->这其实是在操作mysql里自带的一张表  里面专门用来存用户的

 

主键约束---->唯一     一张表最多一个,最少零个,不能为空

自增长约束------->不让改

 

 

 

select    *  from  表名  order by 字段  desc,字段  desc;

 

其实它还是按第一个字段降序排,只是在第一个字段中出现重复值时它就会按第二个字段排序

 

 

select 字段 from 表名 group by 字段;

上面这两个字段相同  就是看这个字段有多少个不同的值

 

select   sum(成绩)  from 表名  group  by 字段; ------->这是按某个字段来查看这个字段所有不同成绩的总和

 

 

 

视图

2013年10月14日

11:12

 

view

 

 

作用:当对sql语句进行再次筛选时,必须使用视图(将复杂查询语句的简单化)

 

create  view  newsView

as 

select  * from newsArticale a,newsTypes b  where a.typeId=b.typeId;

 

 

 

select * from newsView  order by hints  desc  limit 0,6;

------------->操作view就是对view操作后得到的结果再次进行查询,即,再次筛选

 

 

 

 

 

 

 

 

 

 

 

创建视图

create view 视图名

as

     select语句;

 

create view myview

as 

     select  * from student;

 

 

查看视图

1、show tables;

2、information_schema库->tables表

select * from tables where table_type='view';

select * from tables where table_type='view';

 

 

 

 

 

使用视图(把视图当作表来使用)

select * from student;

select * from student where .... limite 0,6;

 

 

 

修改视图

alter  view 视图名

as 

     select语句;

 

 

 

 

drop view myview;                      

 

show tables;

 

上面就是创建并加入一条要执行的语句

 

 

 

 

 

视图注意:

1、将复杂的select 语句简单化

2、将视图当表来使用

3、不建议对视图执行insert、update、delete操作

因为视图里放的都是些多表查询语句,如果对它进行增删改会改乱记录

 

查看当前库中所有视图

1、show tables;

2 、information_schema;  ------->库  里面放着用户建立的视图 ----表

 

table_schema:表所在的库名

table_name:表的表名

 table_type:表的分类(表、视图)

engine:表的存储引擎

 

select   table_schema,table_name,table_type,engine from information_schema where 

 

 

 

 

 

 

 

触发器 --->只对增删改起作用

2013年10月14日

11:46

 

触发器trigger(触发器就是数据库中的事件)

作用:当对表进行insert、update、delete操作时,是否执行其它操作

 

触发器的类型:insert、update、delete

触发执行的时间:before、after

 

创建触发器

create trigger  触发器名

before | after           insert | update | delete

 

 

对表进行delete操作时,要干其它的活

1、干活

2、执行delete语句

 

before: 干活、执行delete

after:执行delete、干活

 

 

delimiter  //

create trigger 触发器名

before|after  insert|update|delete

on 表名

for each row

begin

sql语句;

sql语句;

sql语句;

end //

delimiter ;

 

 

 

修改触发器

delimiter  //

drop trigger if exists  触发器的名字//

create trigger 触发器名

before|after  insert|update|delete

on 表名

for each row

begin

sql语句;

sql语句;

sql语句;

end //

delimiter ;

---------------其实以上是先删再创建,不是真正的修改

 

===========触发器没有修改

 

 

 

删除触发器

1、drop trigger 触发器名;

2、触发器是加在表上的,所以册掉表也是一样

3、当然删掉库就能实现了

 

 

 

查看现存的触发器

information_schema库->triggers表

use information_schema;

select * from triggers;

 

 

trigger_name:触发器名

event_manipulation:触发器类型

event_object_table:  触发器所属的表

select trigger_schema,trigger_name,event_manpulation,event_object_table from trigger;

 

 

 

 

 

触发器总结:

1、触发器的原理及作用

2、创建或修改触发器、删除触发器

3、触发器使用(由系统自动调用)

4、查看触发器相关信息

 

 

 

 

 

 

 

存储过程 --->对查询无用---php无法获取到存储过程中查到的结果集

2013年10月14日

14:52

存储过程procedure(数据库中的自定义函数)

作用:一次编写,多次调用(解决代码重--chong用)----->类似函数

 

 

创建存储过程

delimiter //

create procedure 存储过程名(变量名  数据类型,变量名  数据类型,变量名  数据类型.....)

begin

sql语句;

sql语句;

sql语句;

sql语句;

sql语句;

end  //

delimiter

 

非要修改,可以这样

delimiter //

drop procedure if exists 存储过程名 //

create procedure 存储过程名(变量名  数据类型,变量名  数据类型,变量名  数据类型.....)

begin

sql语句;

sql语句;

sql语句;

sql语句;

sql语句;

end  //

delimiter

 

 

 

 

删除存储过程

drop  procedure  存储过程;

 

 

调用存储过程

all    存储过程(值,值,值,值,值....);

 

 

 

以下为一个实例

 

delimiter //

drop if exists hello//

create procedure hello(id int)

begin

select * from classInfo where claName=值;

end //

delimiter;

 

call hello(1);

 

----->传参时,如果传的是字符或字符串,都得用单引号,没有双引这一说

 

 

 

 

 

 

 

 

delimiter //

drop procedure if exists hello//

create procedure hello(id int)

begin

  select * from classInfo where claId=id;

end //

delimiter ;

 

call hello(1);

 

delimiter //

drop procedure if exists hello//

create procedure hello(name varchar(20))

begin

  select * from classInfo where claName=name;

end //

delimiter ;

 

call hello('php1310');

 

 

delimiter //

drop procedure if exists hello//

create procedure hello(id int,name varchar(20))

begin

  select * from classInfo

    where claId=id and claName=name;

end //

delimiter ;

 

call hello(10,'php1300');

 

 

存储过程参数的分类

输入参数:值是从外--->内

输出参数:值是从内--->外

 

输入参数

create procedure hello(变量 数据类型)

begin

  sql语句;

end

create procedure hello(in 变量 数据类型)    ------>传入参

begin

  sql语句;

end

 

delimiter //

drop procedure if exists hello//

create procedure hello(in id int)

begin

  select * from classInfo where claId=id;

end //

delimiter ;

 

call hello(1);

 

delimiter //

drop procedure if exists hello//

create procedure hello(in id int,in name varchar(20))

begin

  select * from classInfo

    where claId=id and claName=name;

end //

delimiter ;

 

call hello(1,'php1303');

 

 

输出参数

create procedure hello(out 变量 数据类型)

begin

  给变量赋值(给输出参数赋值)

  sql语句;

  sql语句;

  sql语句;

end

call hello(@名);

select @名;

 

delimiter //

drop procedure if exists hello//

create procedure hello(out name varchar(20))

begin

  #给name这个输出参数赋值

  select claName into name from classInfo

    where claId=1;

end//

delimiter ;

 

call hello(@aaa);

select @aaa as rst;

 

 

 

delimiter //

drop procedure if exists hello//

create procedure hello(in id int,out name varchar(20))

begin

  select claName into name from classInfo

    where claId=id;

end //

delimiter ;

 

call hello(10,@haha);

select @haha as claName;

 

 

 

?========>里面的SQL语句写update出错

 

 

=========存储器没有修改

 

 

 

 

 

 

查看现存的所有存储过程

 

mysql库-> proc表

db:存储过程的名

select db,name from proc;

 

 

存储过程总结

 

1、存储过程的原理及作用

2、创建或修改存储过程、删除存储过程、调用存储过程

3、创建存储过程时:参数,调用时:传值

4、参数的分类:输入参数、输出参数

5、查看现存的存储过程

 

存储过程与触发器的区别

1、存储过程可以有参数、触发器没有参数

2、存储过程必须由用户调用,触发器由系统自动调用

3、存储过程、触发器都能独立的完成相应的任务

4、存储过程、触发器都是一次编写,多次调用----->向表里面添加一条记录系统就会自动调用一次触发器

 

 

====================================================

存储过程适用地方

----存储过程,存储过程,顾名思意-------------> 当然是用在存储内容的时候

 

添加内容和删除内容时

 

 

 

SQL编程(T--SQL   transaction  SQL编程)

2013年10月15日

10:20

事务--transaction

知识点:

1、定义变量

2、简单运算

3、判断

4、循环

 

SQL编程出现的地方:trigger  、 procedure

数据库中的输出语句(将文字信息打印在控制台)

select '内容' as msg;  #输出文字信息

select 123 as num;  #输出123这个数字

select @变量;  #将@变量的值输出

select current_timestamp;  #将当前时间输出到控制台

 

 

定义变量

declare  变量名  数据类型;

declare  变量名  数据类型  default   值;

 

 

定义变量注意:在定义变量前,不能出现其他任何代码

 

 

delimiter  //

drop  procedure  if exists  hello //

create   procedure    hello()

begin

#定义变量

declare   a  int;

declare   b int  default  10;

declare   name   varchar(20) default '张三';

 #输出变量

select a,name;

end  //

delimiter;

 

 

 

变量的赋值

1、set  变量名   =  值;

2、set  变量名  =   (select classId from classinfo where id=2  ----->不能一次一堆 ,只能是一个结果,因为不能同时赋两个给一个变量);

3、select 字段 into 变量名 from 表名 where 条件;4、declare 变量名 数据类型 default 值;

 

 

delimiter //

drop procedure if exists hello//

create procedure hello()

begin

  declare stuCount int;

  #将学生总数赋给stuCount

  set stuCount = (select count(*) from student);

  select stuCount;

end //

delimiter ;

 

 

delimiter //

drop procedure if exists hello//

create procedure hello()

begin

  declare name varchar(20);

  #将claId=10班级名称赋给name变量

  set name = (select claName from classInfo where claId=10);

  select name;

end //

delimiter ;

 

 

delimiter //

drop procedure if exists hello//

create procedure hello()

begin

  declare stuCount int;

  #查询所有学生的个数,并赋给stuCount变量

  select count(*) into stuCount from student;

  select stuCount;

end //

delimiter ;

 

 

delimiter //

drop procedure if exists hello//

create procedure hello()

begin

  declare className varchar(20);

  #给className变量赋值

  select claName into className from classInfo where claId=10;

  select className;

end //

delimiter ;

 

 

delimiter //

drop procedure if exists hello//

create procedure hello()

begin

  declare a int;

  declare address varchar(50);

  #给变量赋值

  set a = 100;

  set address = '北京市海淀区';

  select address;

end //

delimiter ;

 

 

 

 

 

 

运算符

算术运算符:+  -  *  /

比较运算符:<  <=  >  >=  =  !=  <>

逻辑运算符:and  or  not

 

 

delimiter //

drop procedure if exists hello//

create procedure hello()

begin

  declare a int default 10;

  set a = a+1;

  select a;

end //

delimiter ;

 

delimiter //

drop procedure if exists hello//

create procedure hello()

begin

  declare a int default 10;

  set a = a + 3;

  select a;

end //

delimiter ;

 

delimiter //

drop procedure if exists hello//

create procedure hello()

begin

  declare a int default 10;

  declare b int default 20;

  declare c int;

  set c = a+b;

  select c;

end //

delimiter ;

 

 

 

 

 

判断语句

 

if  条件  then

逻辑代码;

end if;

 

 

if  条件  then

逻辑代码;

else

逻辑代码;

end if;

 

 

if  条件  then

逻辑代码;

elseif  条件  then

逻辑代码;

else

逻辑代码;

end if;

 

-------------------------------

 

delimiter //

drop procedure if exists hello//

create procedure hello()

begin

  declare age int default 70;

  if age<30 then

    select '不到三十' as msg;

  elseif age=30 then

    select '正好三十' as msg;

  else

    select '超过三十' as msg;

  end if;

end //

delimiter ;

 

 

delimiter //

drop procedure if exists hello//

create procedure hello()

begin

  declare age int default 10;

  if age<30 then

    select '不到三十' as age;

  end if;

end //

delimiter ;

 

 

---------------------------------------------------------------------------------------------

 

 

 

 

 

 

 

 

 

 

 

 

 

 

=========php   js中循环

while   do....while      for   

 

 

循环语句----sql

1、while循环

while  条件  do

 

 

2、repeat循环

repeat

逻辑代码;

until   条件   end  repeat;

 

3、loop循环

名:loop

逻辑代码;

if   条件   then

     leave   名;

end  if;

end   loop;

 

 

名--->不能是汉字,不能是关键字,不能以数字开头

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

===================例子================

 

 

新闻网:存储过程的例子

例子一:删除一个新闻分类typeId=3

        数据库中的一个系统函数:row_count()

        exam1.php文件

delimiter //

drop procedure if exists delNewsType//

create procedure delNewsType(tid int,out nums int)

begin

  #存储受影响的行数的总和

  declare rowCount int default 0;

  #删除这些新闻的所有评论

  delete from reviews

    where articleId in (select articleId from newsArticles where typeId=tid);

  set rowCount = rowCount + row_count();

  #删除该分类下的所有新闻

  delete from newsArticles where typeId=tid;

  set rowCount = rowCount + row_count();

  #删除新闻分类

  delete from newsTypes where typeId=tid;

  set rowCount = rowCount + row_count();

  set nums = rowCount;#将受影响行数的总和赋给输出参数

end //

delimiter ;

 

call delNewsType(3,@aaa);

select @aaa;

 

例子二:添加一个新闻,并修改分类下的新闻数量

        exam2.php

delimiter //

drop procedure if exists addNews//

create procedure addNews(content1 text,title1 varchar(50),typeId1 int,userName1 varchar(20))

begin

  #修改新闻数量

  declare newsCount int;

  set newsCount = (select articleNums from newsTypes where typeId=typeId1);

  set newsCount = newsCount+1;

  update newsTypes set articleNums=newsCount where typeId=typeId1;

 

  #declare newsCount int;

  #select articleNums into newsCount from newsTypes where typeId=typeId1;

  #set newsCount = newsCount+1;

  #update newsTypes set articleNums=newsCount where typeId=typeId1;

 

  #update newsTypes set articleNums=articleNums+1 where typeId=typeId1;

  

  #将当前新闻添加到newsArticles表

  insert into newsArticles(content,title,typeId,userName)

    values(content1,title1,typeId1,userName1);

end //

delimiter ;

 

call addNews('内容',"标题",1,'admin');

 

 

例子三:删除一个新闻,删除该新闻下的所有评论

        修改分类表中的新闻数量  articleId=1

        exam3.php

delimiter //

drop procedure if exists delNews//

create procedure delNews(aid int)

begin

  #将该分类下的新闻数量减一

  update newsTypes set articleNums=articleNums-1

    where typeId = (select typeId from newsArticles where articleId=aid);

  #删除该新闻的所有评论

  delete from reviews where articleId=aid;

  #删除新闻

  delete from newsArticles where articleId=aid;

end //

delimiter ;

 

call delNews(1);

------------------------------------------------

必须使用存储过程的场合

完成一个任务:需要多个sql语句

------------------------------------------------

必须使用触发器的场合(所有的触发器都可以用存储过程来代替)

对表进行insert、update、delete操作的同时:

还要完成其他的任务(不能带参数)

------------------------------------------------

必须使用视图的场合(将复杂的查询语句简单化)

有一个复杂的多表查询语句时:考虑将复杂的查询语句

放到一个视图中

-------------------------------------------------

索引index:隐藏编号

作用:提高表的查询速度

库->表->字段(注意:索引是作用在字段上)

适合添加索引的字段:经常当做where条件的字段

 

索引的分类

1、主键索引:表的主键

   建表的同时指定主键约束

2、普通索引:非主键的字段,该字段还经常充当where条件

   create index 索引名 on 表名(字段名);

   drop index 索引名 on 表名;

   create index aaa on classInfo(claName);

   drop index aaa on classInfo;

3、唯一索引:非主键的字段,该字段还经常充当where条件且该字段不能出现重复值

   1)建表时,给字段指定唯一约束

   2)create unique index 索引名 on 表名(字段名);

     drop index 索引名 on 表名;

     create unique index aaa on classInfo(claName);

     drop index aaa on classInfo;

4、全文索引:非主键的字段,该字段还经常充当where条件(模糊查询)

   create fulltext index 索引名 on 表名(字段名);

   drop index 索引名 on 表名;

   create fulltext index aaa on classInfo(claName);

 

 

 

--------这样获取-----

 

 

 

 

 

 

-------------

 

 

 

 

 

 

 

 

 

 

 

 

 

------->php获取返回值?

-------------网上回答---------

declare @result as varchar--返回值的类型

exec @result=proc--存储过程及参数

select @result

 

$tsql .= "call a(@b);";

$tsql .= "select @b;";

 

 

 

 

======================================

 

 

 

PHP code

<?php
     define('CLIENT_MULTI_RESULTS', 131072);

     $link = mysql_connect("127.0.0.1", "root", "",1,CLIENT_MULTI_RESULTS) or die("Could not connect: ".mysql_error());
     mysql_select_db("vs") or die("Could not select database");
  ?>
  
 <?php
          $result = mysql_query("call get_news_from_class_id(2)") or die("Query failed:" .mysql_error());
         while($row = mysql_fetch_array($result, MYSQL_ASSOC))
         {
                $line = '<tr><td><a target = _blank href=\''.$row["url"].'\'>'.$row["title"].'('.$row["page_time"].')'.'</a></td></tr>';
                 echo $line;
                printf("\n");
 
         }
         mysql_free_result($result);
?>
 
 <?php
     mysql_close($link);
 ?>

 

 

 

 

索引index ---存储引擎

2013年10月15日

15:28

 

隐藏编号

 

作用:提高表的查询速度

库-> 表->字段(注意:索引是作用在字段上)

适合添加索引的字段:经常当做where条件的字段

 

索引的分类

1、主键索引:表的主键

建表的同时指定主键约束

2、普通索引:非主键的字段,该字段还经常充当where条件

create  index  索引名  on  表名(字段);

drop  index  索引名  on  表名;             ========>删除索引

create  index  aaa  on classInfo(claName);

drop  index  aaa on classInfo;

3、唯一索引:非主键的字段,该字段还经常充当where条件且

 

 

 

 

 

 

 

 

 

4、全文索引:非主键的字段,该字段还经常充当where条件(模糊查询)

create  fulltext  index  索引名  on  表名(字段名);

drop  index  索引名  on  表名;

 

 

常用的三种索引

1、主键索引:建表时都需指定主键

2、表中存在经常充当where条件的字段

1)该字段有重复值:添加普通索引

2)该字段无重复值:添加唯一索引

 

create  unique  index 索引名  on  表名(字段名);

 

 

 

 

 

存储引擎(表的类型)------->名字不区分 大小写

1、ISAM     查询速度相当快(增删改相对慢点)、支持全文索引、不支持外键、不支持事务、不支持check

2、MyISAM   ISAM升级版

3、HEAP(Memory) 速度快(增删改查)、数据驻留在内存

4、InnoDB

 

 

 

 

 

 

修改mysql本身的存储引擎

1、修改my.ini配置文件

default-storage-engine=InnoDB

注意:存储引擎修改后再新建的表才是新的存储引擎

2、建表的同时指定存储引擎

mysql4.0及以前的版本

create  table  表名

(

字段        数据类型   约束,

字段        数据类型   约束,

字段        数据类型   约束

)type=引擎名;

 

 

mysql5.0及以后的版本

create   table   表名

(

字段    数据类型   约束,

字段    数据类型   约束,

字段    数据类型   约束,

字段    数据类型   约束,

字段    数据类型   约束

)engine=引擎名;

 

给表添加全文索引

create table userInfo

(

userName  varchar(20)  primary  key,

password   varchar(20)   not null

)engine:MyISAM;

 

create  fulltext  index  aaa on  userInfo(password);

drop index aaa  on  userInfo;

 

 

 

索引、存储引擎总结:

1、索引的原理、作用

2、索引的分类

3、添加索引、删除索引

4、存储引擎的作用及原理

5、每个存储引擎的特征

6、指定存储引擎

 

 

 

 

---------------------

 

全文索引 针对中文---比较有效果

 

 

主键索引、唯一索引、普通索引-------->只针对非中文字

 

 

 

 

 

 

 

外键

2013年10月16日

11:32

 

能保证数据的完整性*********

 

 

就是外键里出现的数据只能是主表里关联的那个字段里出现的数据

 

 

标识变量

2013年10月15日

11:47

 

就是标识该变量是否有执行过

 

 

事物

2013年10月15日

16:32

insert   into  表名(字段,字段,字段) values(值,值,值);

 

事务Transaction  ===>

 

 

作用:保持数据的完整性(要成功全部成功、要失败全部失败)

特点:原子性(事物的最小单位,不再被分隔)、一致性、隔离性(如远程操作数据,本地也在开,也就是多个事物间是相对独立的,互不影响的)、持久性

 

 

特征

原子性:事务是不可分割的最小单位

一致性:事务中的多个操作最终状态是一致的

隔离性:同一数据库多个事务彼此间是独立的,互不干扰

持久性:事务的最终状态,要成功就成功,要失败就失败

 

 

开启一个事务

干活

。。。

。。。

。。。

失败了。------->  这个事务就是失败了,再了不会成功了------->时间不能倒流

 

---------------->这是mysql的一个自动机制

 

---------------->事物的使用

start   transaction;       ========>开启一个事物

sql语句;

sql语句;

sql语句;

sql语句;

sql语句;

#结束事物

commit;    #-->这个#号是注释符 commit类似submit意思====>(成功、事务结束)

rollback;   #回滚事务(事务、事务结束)==========>相当这件事白做了,同时事务也结束了

 

 

 

结束事物的方法:commit、rollback

事务的最终状态:commit、rollback

 

 

 

 

 

====================--------------->开启一个事物,这样我们在修改真实重要的数据时,万一自己改错了,这时可以用事务的回滚点来挽回损失,当自己检查确保没问题时,再commit  即

 

 

 

 

 

回滚点

 start   transaction;  #开启一个事务

sql语句;

sql语句;

sql语句;

savepoint  名;  #回滚点

sql语句;

sql语句;

sql语句;

rollback   to  名;    #回滚到指定的回滚点

 

 

注意:rollback   to  回滚点名;    #不会结束事务

 

 

事务总结

1、事务的原理及作用

2、事务的特点

3、开启事务、回滚点、提交、

 

 

--------------------------------------------------------------------------------

 

 

不支持事物的sql语句: create   drop  alter  truncate

支持事务的sql语句:insert   update  delete

 

 

 

2013年10月16日

2:33

MySQL性能优化的21个最佳实践

 

 

 

日期:2010-7-22  我要评论 

 

 

 

 

   

大 | 中 | 小.

投稿

 打印

 

 

 

导读:本文介绍了MySQL性能优化的21个最佳实践,今天,数据库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显。

 

关键词:MySQL性能优化 最佳实践 数据库操作  

  

 

  今天,数据库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显。关于数据库的性能,这并不只是DBA才需要担心的事,而这更是我们程序员需要去关注的事情。当我们去设计数据库表结构,对操作数据库时(尤其是查表时的SQL语句),我们都需要注意数据操作的性能。这里,我们不会讲过多的SQL语句的优化,而只是针对MySQL这一Web应用最多的数据库。希望下面的这些优化技巧对你有用。

 

 

Advertisement

   

  1. 为查询缓存优化你的查询

 

  大多数的MySQL服务器都开启了查询缓存。这是提高性最有效的方法之一,而且这是被MySQL的数据库引擎处理的。当有很多相同的查询被执行了多次的时候,这些查询结果会被放到一个缓存中,这样,后续的相同的查询就不用操作表而直接访问缓存结果了。

 

  这里最主要的问题是,对于程序员来说,这个事情是很容易被忽略的。因为,我们某些查询语句会让MySQL不使用缓存。请看下面的示例:

 

   

 

 

 

 

  上面两条SQL语句的差别就是 CURDATE() ,MySQL的查询缓存对这个函数不起作用。所以,像 NOW() 和 RAND() 或是其它的诸如此类的SQL函数都不会开启查询缓存,因为这些函数的返回是会不定的易变的。所以,你所需要的就是用一个变量来代替MySQL的函数,从而开启缓存。

 

  2. EXPLAIN 你的 SELECT 查询

 

  使用 EXPLAIN 关键字可以让你知道MySQL是如何处理你的SQL语句的。这可以帮你分析你的查询语句或是表结构的性能瓶颈。

 

  EXPLAIN 的查询结果还会告诉你你的索引主键被如何利用的,你的数据表是如何被搜索和排序的……等等,等等。

 

  挑一个你的SELECT语句(推荐挑选那个最复杂的,有多表联接的),把关键字EXPLAIN加到前面。你可以使用phpmyadmin来做这个事。然后,你会看到一张表格。下面的这个示例中,我们忘记加上了group_id索引,并且有表联接:

 

   

 

 

 

 

  当我们为 group_id 字段加上索引后:

 

   

 

 

 

 

  我们可以看到,前一个结果显示搜索了 7883 行,而后一个只是搜索了两个表的 9 和 16 行。查看rows列可以让我们找到潜在的性能问题。

 

  3. 当只要一行数据时使用 LIMIT 1

 

  当你查询表的有些时候,你已经知道结果只会有一条结果,但因为你可能需要去fetch游标,或是你也许会去检查返回的记录数。

 

  在这种情况下,加上 LIMIT 1 可以增加性能。这样一样,MySQL数据库引擎会在找到一条数据后停止搜索,而不是继续往后查少下一条符合记录的数据。

 

  下面的示例,只是为了找一下是否有“中国”的用户,很明显,后面的会比前面的更有效率。(请注意,第一条中是Select *,第二条是Select 1)

 

   

 

 

 

 

  4. 为搜索字段建索引

 

  索引并不一定就是给主键或是唯一的字段。如果在你的表中,有某个字段你总要会经常用来做搜索,那么,请为其建立索引吧。

 

   

 

 

 

 

  从上图你可以看到那个搜索字串 “last_name LIKE ‘a%’”,一个是建了索引,一个是没有索引,性能差了4倍左右。

 

  另外,你应该也需要知道什么样的搜索是不能使用正常的索引的。例如,当你需要在一篇大的文章中搜索一个词时,如: “WHERE post_content LIKE ‘%apple%’”,索引可能是没有意义的。你可能需要使用MySQL全文索引 或是自己做一个索引(比如说:搜索关键词或是Tag什么的)

 

  5. 在Join表的时候使用相当类型的例,并将其索引

 

  如果你的应用程序有很多 JOIN 查询,你应该确认两个表中Join的字段是被建过索引的。这样,MySQL内部会启动为你优化Join的SQL语句的机制。

 

  而且,这些被用来Join的字段,应该是相同的类型的。例如:如果你要把 DECIMAL 字段和一个 INT 字段Join在一起,MySQL就无法使用它们的索引。对于那些STRING类型,还需要有相同的字符集才行。(两个表的字符集有可能不一样)

 

   

 

 

 

 

  6. 千万不要 ORDER BY RAND()

 

  想打乱返回的数据行?随机挑一个数据?真不知道谁发明了这种用法,但很多新手很喜欢这样用。但你确不了解这样做有多么可怕的性能问题。

 

  如果你真的想把返回的数据行打乱了,你有N种方法可以达到这个目的。这样使用只让你的数据库的性能呈指数级的下降。这里的问题是:MySQL会不得不去执行RAND()函数(很耗CPU时间),而且这是为了每一行记录去记行,然后再对其排序。就算是你用了Limit 1也无济于事(因为要排序)

 

  下面的示例是随机挑一条记录

 

   

 

 

 

 

  7. 避免 SELECT *

 

  从数据库里读出越多的数据,那么查询就会变得越慢。并且,如果你的数据库服务器和WEB服务器是两台独立的服务器的话,这还会增加网络传输的负载。

 

  所以,你应该养成一个需要什么就取什么的好的习惯。

 

   

 

 

 

 

  8. 永远为每张表设置一个ID

 

  我们应该为数据库里的每张表都设置一个ID做为其主键,而且最好的是一个INT型的(推荐使用UNSIGNED),并设置上自动增加的AUTO_INCREMENT标志。

 

  就算是你 users 表有一个主键叫 “email”的字段,你也别让它成为主键。使用 VARCHAR 类型来当主键会使用得性能下降。另外,在你的程序中,你应该使用表的ID来构造你的数据结构。

 

  而且,在MySQL数据引擎下,还有一些操作需要使用主键,在这些情况下,主键的性能和设置变得非常重要,比如,集群,分区……

 

  在这里,只有一个情况是例外,那就是“关联表”的“外键”,也就是说,这个表的主键,通过若干个别的表的主键构成。我们把这个情况叫做“外键”。比如:有一个“学生表”有学生的ID,有一个“课程表”有课程ID,那么,“成绩表”就是“关联表”了,其关联了学生表和课程表,在成绩表中,学生ID和课程ID叫“外键”其共同组成主键。

 

  9. 使用 ENUM 而不是 VARCHAR

 

  ENUM 类型是非常快和紧凑的。在实际上,其保存的是 TINYINT,但其外表上显示为字符串。这样一来,用这个字段来做一些选项列表变得相当的完美。

 

  如果你有一个字段,比如“性别”,“国家”,“民族”,“状态”或“部门”,你知道这些字段的取值是有限而且固定的,那么,你应该使用 ENUM 而不是 VARCHAR。

 

  MySQL也有一个“建议”(见第十条)告诉你怎么去重新组织你的表结构。当你有一个 VARCHAR 字段时,这个建议会告诉你把其改成 ENUM 类型。使用 PROCEDURE ANALYSE() 你可以得到相关的建议。

 

  10. 从 PROCEDURE ANALYSE() 取得建议

 

  PROCEDURE ANALYSE() 会让 MySQL 帮你去分析你的字段和其实际的数据,并会给你一些有用的建议。只有表中有实际的数据,这些建议才会变得有用,因为要做一些大的决定是需要有数据作为基础的。

 

  例如,如果你创建了一个 INT 字段作为你的主键,然而并没有太多的数据,那么,PROCEDURE ANALYSE()会建议你把这个字段的类型改成 MEDIUMINT 。或是你使用了一个 VARCHAR 字段,因为数据不多,你可能会得到一个让你把它改成 ENUM 的建议。这些建议,都是可能因为数据不够多,所以决策做得就不够准。

 

  在phpmyadmin里,你可以在查看表时,点击 “Propose table structure” 来查看这些建议

 

   

 

 

 

 

  一定要注意,这些只是建议,只有当你的表里的数据越来越多时,这些建议才会变得准确。一定要记住,你才是最终做决定的人。

 

  11. 尽可能的使用 NOT NULL

 

  除非你有一个很特别的原因去使用 NULL 值,你应该总是让你的字段保持 NOT NULL。这看起来好像有点争议,请往下看。

 

  首先,问问你自己“Empty”和“NULL”有多大的区别(如果是INT,那就是0和NULL)?如果你觉得它们之间没有什么区别,那么你就不要使用NULL。(你知道吗?在 Oracle 里,NULL 和 Empty 的字符串是一样的!)

 

  不要以为 NULL 不需要空间,其需要额外的空间,并且,在你进行比较的时候,你的程序会更复杂。 当然,这里并不是说你就不能使用NULL了,现实情况是很复杂的,依然会有些情况下,你需要使用NULL值。

 

 

  12. Prepared Statements

 

  Prepared Statements很像存储过程,是一种运行在后台的SQL语句集合,我们可以从使用 prepared statements 获得很多好处,无论是性能问题还是安全问题。

 

  Prepared Statements 可以检查一些你绑定好的变量,这样可以保护你的程序不会受到“SQL注入式”攻击。当然,你也可以手动地检查你的这些变量,然而,手动的检查容易出问题,而且很经常会被程序员忘了。当我们使用一些framework或是ORM的时候,这样的问题会好一些。

 

  在性能方面,当一个相同的查询被使用多次的时候,这会为你带来可观的性能优势。你可以给这些Prepared Statements定义一些参数,而MySQL只会解析一次。

 

  虽然最新版本的MySQL在传输Prepared Statements是使用二进制形势,所以这会使得网络传输非常有效率。

 

  当然,也有一些情况下,我们需要避免使用Prepared Statements,因为其不支持查询缓存。但据说版本5.1后支持了。

 

  在PHP中要使用prepared statements,你可以查看其使用手册:mysqli 扩展 或是使用数据库抽象层,如: PDO.

 

   

 

 

 

 

  13. 无缓冲的查询

 

  正常的情况下,当你在当你在你的脚本中执行一个SQL语句的时候,你的程序会停在那里直到没这个SQL语句返回,然后你的程序再往下继续执行。你可以使用无缓冲查询来改变这个行为。

 

 

  mysql_unbuffered_query() 发送一个SQL语句到MySQL而并不像mysql_query()一样去自动fethch和缓存结果。这会相当节约很多可观的内存,尤其是那些会产生大量结果的查询语句,并且,你不需要等到所有的结果都返回,只需要第一行数据返回的时候,你就可以开始马上开始工作于查询结果了。

 

  然而,这会有一些限制。因为你要么把所有行都读走,或是你要在进行下一次的查询前调用 mysql_free_result() 清除结果。而且, mysql_num_rows() 或 mysql_data_seek() 将无法使用。所以,是否使用无缓冲的查询你需要仔细考虑。

 

  14. 把IP地址存成 UNSIGNED INT

 

  很多程序员都会创建一个 VARCHAR(15) 字段来存放字符串形式的IP而不是整形的IP。如果你用整形来存放,只需要4个字节,并且你可以有定长的字段。而且,这会为你带来查询上的优势,尤其是当你需要使用这样的WHERE条件:IP between ip1 and ip2。

 

  我们必需要使用UNSIGNED INT,因为 IP地址会使用整个32位的无符号整形。

 

  而你的查询,你可以使用 INET_ATON() 来把一个字符串IP转成一个整形,并使用 INET_NTOA() 把一个整形转成一个字符串IP。在PHP中,也有这样的函数 ip2long() 和 long2ip()。

 

   

 

 

 

 

  15. 固定长度的表会更快

 

  如果表中的所有字段都是“固定长度”的,整个表会被认为是 “static” 或 “fixed-length”。 例如,表中没有如下类型的字段: VARCHAR,TEXT,BLOB。只要你包括了其中一个这些字段,那么这个表就不是“固定长度静态表”了,这样,MySQL 引擎会用另一种方法来处理。

 

  固定长度的表会提高性能,因为MySQL搜寻得会更快一些,因为这些固定的长度是很容易计算下一个数据的偏移量的,所以读取的自然也会很快。而如果字段不是定长的,那么,每一次要找下一条的话,需要程序找到主键。

 

  并且,固定长度的表也更容易被缓存和重建。不过,唯一的副作用是,固定长度的字段会浪费一些空间,因为定长的字段无论你用不用,他都是要分配那么多的空间。

 

  使用“垂直分割”技术(见下一条),你可以分割你的表成为两个一个是定长的,一个则是不定长的。

 

  16. 垂直分割

 

  “垂直分割”是一种把数据库中的表按列变成几张表的方法,这样可以降低表的复杂度和字段的数目,从而达到优化的目的。(以前,在银行做过项目,见过一张表有100多个字段,很恐怖)

 

  示例一:在Users表中有一个字段是家庭地址,这个字段是可选字段,相比起,而且你在数据库操作的时候除了个人信息外,你并不需要经常读取或是改写这个字段。那么,为什么不把他放到另外一张表中呢? 这样会让你的表有更好的性能,大家想想是不是,大量的时候,我对于用户表来说,只有用户ID,用户名,口令,用户角色等会被经常使用。小一点的表总是会有好的性能。

 

  示例二: 你有一个叫 “last_login” 的字段,它会在每次用户登录时被更新。但是,每次更新时会导致该表的查询缓存被清空。所以,你可以把这个字段放到另一个表中,这样就不会影响你对用户ID,用户名,用户角色的不停地读取了,因为查询缓存会帮你增加很多性能。

 

  另外,你需要注意的是,这些被分出去的字段所形成的表,你不会经常性地去Join他们,不然的话,这样的性能会比不分割时还要差,而且,会是极数级的下降。

 

  17. 拆分大的 DELETE 或 INSERT 语句

 

  如果你需要在一个在线的网站上去执行一个大的 DELETE 或 INSERT 查询,你需要非常小心,要避免你的操作让你的整个网站停止相应。因为这两个操作是会锁表的,表一锁住了,别的操作都进不来了。

 

  Apache 会有很多的子进程或线程。所以,其工作起来相当有效率,而我们的服务器也不希望有太多的子进程,线程和数据库链接,这是极大的占服务器资源的事情,尤其是内存。

 

  如果你把你的表锁上一段时间,比如30秒钟,那么对于一个有很高访问量的站点来说,这30秒所积累的访问进程/线程,数据库链接,打开的文件数,可能不仅仅会让你泊WEB服务Crash,还可能会让你的整台服务器马上掛了。

 

  所以,如果你有一个大的处理,你定你一定把其拆分,使用 LIMIT 条件是一个好的方法。下面是一个示例:

 

   

 

 

 

 

  18. 越小的列会越快

 

  对于大多数的数据库引擎来说,硬盘操作可能是最重大的瓶颈。所以,把你的数据变得紧凑会对这种情况非常有帮助,因为这减少了对硬盘的访问。

 

  参看 MySQL 的文档 Storage Requirements 查看所有的数据类型。

 

  如果一个表只会有几列罢了(比如说字典表,配置表),那么,我们就没有理由使用 INT 来做主键,使用 MEDIUMINT, SMALLINT 或是更小的 TINYINT 会更经济一些。如果你不需要记录时间,使用 DATE 要比 DATETIME 好得多。

 

  当然,你也需要留够足够的扩展空间,不然,你日后来干这个事,你会死的很难看,参看Slashdot的例子(2009年11月06日),一个简单的ALTER TABLE语句花了3个多小时,因为里面有一千六百万条数据。

 

  19. 选择正确的存储引擎

 

  在 MySQL 中有两个存储引擎 MyISAM 和 InnoDB,每个引擎都有利有弊。酷壳以前文章《MySQL: InnoDB 还是 MyISAM?》讨论和这个事情。

 

  MyISAM 适合于一些需要大量查询的应用,但其对于有大量写操作并不是很好。甚至你只是需要update一个字段,整个表都会被锁起来,而别的进程,就算是读进程都无法操作直到读操作完成。另外,MyISAM 对于 SELECT COUNT(*) 这类的计算是超快无比的。

 

  InnoDB 的趋势会是一个非常复杂的存储引擎,对于一些小的应用,它会比 MyISAM 还慢。他是它支持“行锁” ,于是在写操作比较多的时候,会更优秀。并且,他还支持更多的高级应用,比如:事务。

 

  下面是MySQL的手册

 

  target=”_blank”MyISAM Storage Engine

 

  InnoDB Storage Engine

 

  20. 使用一个对象关系映射器(Object Relational Mapper)

 

  使用 ORM (Object Relational Mapper),你能够获得可靠的性能增涨。一个ORM可以做的所有事情,也能被手动的编写出来。但是,这需要一个高级专家。

 

  ORM 的最重要的是“Lazy Loading”,也就是说,只有在需要的去取值的时候才会去真正的去做。但你也需要小心这种机制的副作用,因为这很有可能会因为要去创建很多很多小的查询反而会降低性能。

 

  ORM 还可以把你的SQL语句打包成一个事务,这会比单独执行他们快得多得多。

 

  目前,个人最喜欢的PHP的ORM是:Doctrine。

 

  21. 小心“永久链接”

 

  “永久链接”的目的是用来减少重新创建MySQL链接的次数。当一个链接被创建了,它会永远处在连接的状态,就算是数据库操作已经结束了。而且,自从我们的Apache开始重用它的子进程后——也就是说,下一次的HTTP请求会重用Apache的子进程,并重用相同的 MySQL 链接。

 

  PHP手册:mysql_pconnect()

 

  在理论上来说,这听起来非常的不错。但是从个人经验(也是大多数人的)上来说,这个功能制造出来的麻烦事更多。因为,你只有有限的链接数,内存问题,文件句柄数,等等。

 

  而且,Apache 运行在极端并行的环境中,会创建很多很多的了进程。这就是为什么这种“永久链接”的机制工作地不好的原因。在你决定要使用“永久链接”之前,你需要好好地考虑一下你的整个系统的架构。

 

TechTarget中国原创内容,原文链接:http://www.searchdatabase.com.cn/showcontent_38045.htm

 

 

Mysql 集群简介和配置 

2013年10月16日

2:34

 

Mysql 集群简介和配置 

先了解一下你是否应该用 mysql 集群。 

减少数据中心结点压力和大数据量处理,采用把 mysql 分布,一个或多个 application 对应一个 mysql 数据库。把几个 mysql 数据库公用的数据做出共享数据,例如购物车,用户对象等等,存在数据结点里面。其他不共享的数据还维持在各自分布的 mysql 数据库本身中。 

  

  

  

集群 Mysql 中名称概念 .( 如上图 ) 

 Sql 结点( SQL node-- 上图对应为 mysqld  : 分布式数据库。包括自身数据和查询中心结点数据 . 

)数据结点 (Data node -- ndbd): 集群共享数据 ( 内存中 ). 

)管理服务器 (Management Server – ndb_mgmd): 集群管理 SQL node,Data node. 

  

.配置 

mysql-max 版本,当然现在 mysql 集群系统 windonws 平台上面不被支持 . 

安装 mysql 就不多说了,网上一打堆,简明扼要。 

A:192.168.1.251 – Data node  Management Server. 

B:192.168.1.254 – SQL node. 

当然,你也可以让一个机器同时为 3 者。 

A,B my.inf 加上: 

[MYSQLD] 

ndbcluster # run NDB engine 

ndb-connectstring=192.168.1.251 # location of MGM node 

  

# Options for ndbd process: 

[MYSQL_CLUSTER] 

ndb-connectstring=192.168.1.251 # location of MGM node 

  

A: /var/lib/mysql-cluster/config.ini 

[NDBD DEFAULT] 

NoOfReplicas=1 # Number of replicas 

DataMemory=80M # How much memory to allocate for data storage 

IndexMemory=18M # How much memory to allocate for index storage 

# For DataMemory and IndexMemory, we have used the 

# default values. Since the "world" database takes up 

# only about 500KB, this should be more than enough for 

# this example Cluster setup. 

# TCP/IP options: 

[TCP DEFAULT] 

portnumber=2202 # This the default; however, you can use any 

# port that is free for all the hosts in cluster 

# Note: It is recommended beginning with MySQL 5.0 that 

# you do not specify the portnumber at all and simply allow 

# the default value to be used instead 

# Management process options: 

[NDB_MGMD] 

hostname=192.168.1.251 # Hostname or IP address of MGM node 

datadir=/var/lib/mysql-cluster # Directory for MGM node logfiles 

# Options for data node "A": 

[NDBD]  

# (one [NDBD] section per data node) 

hostname=192.168.1.251 # Hostname or IP address 

datadir=/usr/local/mysql/data # Directory for this data node's datafiles 

# SQL node options: 

[MYSQLD] 

hostname=192.168.1.254 

#[MYSQLD] # 这个相当于 192.168.1.251 

  

  

启动测试 

  

在管理服务器上面(这里是192.168.1.251): 

                                
                                                
                                
                                
                                                shell> ndb_mgmd -f /var/lib/mysql-cluster/config.ini
                                
                

  

在数据结点服务器上面(依然是192.168.1.251 and more): 

                                
                                                
                                
                                
                                                shell> ndbd --initial (
                                                
                                                                第一次时加 --initial 参数)
                                                
                                                
                                                                
                                                                
                                                
                                
                

  

SQL 结点服务器上面(192.168.1.254): 

                                
                                                
                                
                                
                                                shell> mysqld &
                                
                

  

 251 上面察看 

  

./ndb_mgm 

-- NDB Cluster -- Management Client -- 

ndb_mgm> show 

Connected to Management Server at: 192.168.1.251:1186 

Cluster Configuration 

--------------------- 

[ndbd(NDB)] 1 node(s) 

id=2 @192.168.1.251 (Version: 5.0.22, Nodegroup: 0, Master) 

[ndb_mgmd(MGM)] 1 node(s) 

id=1 @192.168.1.251 (Version: 5.0.22) 

[mysqld(API)] 1 node(s) 

id=3 @192.168.1.254 (Version: 5.0.22) 

  

ok 

关闭集群: 

shell> ndb_mgm -e shutdown 

  

  

5 .基本的集群说明 

1 )在mysql 集群中.当table引擎为NDBCLUSTER时才做集群,其他非NDBCLUSTER表和一般mysql数据库表一样,不会共享数据. NDBCLUSTER 表数据存储在Data node服务器内存中,Data Node可以为1台或多台服务器,它们之间存放共享数据。Data Node服务器可以分组数据copy。 

例如:2,3,4,5 为四台Data Node服务器ID. 2,3为组0。 4,5为组1。 2,3维持数据相同, 4,5维持数据相同。 组0和组1维持数据不同。 

2 ) sql node 服务器中,非NDBCLUSTER数据存在本身数据库中,table引擎为NDBCLUSTER时,数据存储在Data Node 中。当查询NDBCLUSTER表时,它会从Data node集群中提起数据. 

3)Manager server 

管理SQl node 和Data node 状态。 

 

源文档 <http://www.blogjava.net/hellboys/archive/2006/06/28/55507.html

 

 

 

使用php自动发送邮件  

2013年10月16日

2:41

使用php自动发送邮件  

2009-10-01 08:37:38|  分类: linux |  标签: |字号大中小 订阅 

 

作者:zhongxm2007   

url: http://zhongxm2007.blog.163.com/blog/static/2630077420099183738126/

 

概述:在linux系统中,缺省情况下可以使用命令来发送邮件,即使用telnet  ip:25 这种方式来发送邮件,也可以安装php后,使用php的方式来发送邮件。 

     使用php方式发送邮件的特点是:简单方便,只需要两个文件,一个是类文件,另一个是定义发送者用户名,密码,收件人,发送主题等的文件。

 

下面的程序小改可以作为“php自动发送邮件php程序.

 

//smtp.class.php

<?php    

//发送邮件的类    

class Smtp    

{    

   

   

    /* Public Variables */   

    var $smtp_port;    

    var $time_out;    

    var $host_name;    

    var $log_file;    

    var $relay_host;    

    var $debug;    

    var $auth;    

    var $user;    

    var $pass;    

   

    /* Private Variables */     

    var $sock;    

   

    /* Constractor */   

   

   

    function Smtp($relay_host = "", $smtp_port = 25,$auth = false,$user,$pass)    

    {    

        $this->debug = FALSE;    

        $this->smtp_port = $smtp_port;    

        $this->relay_host = $relay_host;    

        $this->time_out = 30; //is used in fsockopen()     

            

        #    

   

        $this->auth = $auth;//auth    

        $this->user = $user;    

        $this->pass = $pass;    

            

        #    

   

        $this->host_name = "localhost"; //is used in HELO command     

        $this->log_file = "";    

   

   

        $this->sock = FALSE;    

    }    

   

   

    /* Main Function */   

   

   

    function sendmail($to, $from, $subject = "", $body = "", $mailtype, $cc = "", $bcc = "", $additional_headers = "")    

    {    

   

   

        $mail_from = $this->get_address($this->strip_comment($from));    

        $body = ereg_replace("(^|(\r\n))(\.)", "\1.\3", $body);    

        $header = "MIME-Version:1.0\r\n";    

   

        if($mailtype=="HTML"){    

            $header .= "Content-Type:text/html\r\n";    

        }    

   

        $header .= "To: ".$to."\r\n";    

   

        if ($cc != "") {    

            $header .= "Cc: ".$cc."\r\n";    

        }    

   

        $header .= "From: $from<".$from.">\r\n";    

        $header .= "Subject: ".$subject."\r\n";    

        $header .= $additional_headers;    

        $header .= "Date: ".date("r")."\r\n";    

        $header .= "X-Mailer:By Redhat (PHP/".phpversion().")\r\n";    

   

        list($msec, $sec) = explode(" ", microtime());    

   

        $header .= "Message-ID: <".date("YmdHis", $sec).".".($msec*1000000).".".$mail_from.">\r\n";    

   

        $TO = explode(",", $this->strip_comment($to));    

   

        if ($cc != "") {    

            $TO = array_merge($TO, explode(",", $this->strip_comment($cc)));    

        }    

   

   

        if ($bcc != "") {    

            $TO = array_merge($TO, explode(",", $this->strip_comment($bcc)));    

        }    

   

        $sent = TRUE;    

   

        foreach ($TO as $rcpt_to) {    

            $rcpt_to = $this->get_address($rcpt_to);    

                

            if (!$this->smtp_sockopen($rcpt_to)) {    

                $this->log_write("Error: Cannot send email to ".$rcpt_to."\n");    

                $sent = FALSE;    

                continue;    

            }    

   

            if ($this->smtp_send($this->host_name, $mail_from, $rcpt_to, $header, $body)) {    

                $this->log_write("E-mail has been sent to <".$rcpt_to.">\n");    

            } else {    

                $this->log_write("Error: Cannot send email to <".$rcpt_to.">\n");    

                $sent = FALSE;    

            }    

   

            fclose($this->sock);    

   

            $this->log_write("Disconnected from remote host\n");    

        }    

   

        return $sent;    

   

    }    

   

/* Private Functions */   

   function smtp_send($helo, $from, $to, $header, $body = "")    

    {    

        if (!$this->smtp_putcmd("HELO", $helo)) {    

   

            return $this->smtp_error("sending HELO command");    

        }    

   

        #auth    

   

        if($this->auth){    

            if (!$this->smtp_putcmd("AUTH LOGIN", base64_encode($this->user))) {    

                return $this->smtp_error("sending HELO command");    

            }    

   

            if (!$this->smtp_putcmd("", base64_encode($this->pass))) {    

                return $this->smtp_error("sending HELO command");    

            }    

        }    

   

        #    

   

        if (!$this->smtp_putcmd("MAIL", "FROM:<".$from.">")) {    

            return $this->smtp_error("sending MAIL FROM command");    

        }    

   

        if (!$this->smtp_putcmd("RCPT", "TO:<".$to.">")) {    

            return $this->smtp_error("sending RCPT TO command");    

        }    

   

        if (!$this->smtp_putcmd("DATA")) {    

            return $this->smtp_error("sending DATA command");    

        }    

   

   

        if (!$this->smtp_message($header, $body)) {    

   

   

            return $this->smtp_error("sending message");    

   

   

        }    

   

   

        if (!$this->smtp_eom()) {    

   

   

            return $this->smtp_error("sending <CR><LF>.<CR><LF> [EOM]");    

   

   

        }    

   

   

        if (!$this->smtp_putcmd("QUIT")) {    

   

   

            return $this->smtp_error("sending QUIT command");    

   

   

        }    

   

   

        return TRUE;    

   

   

    }    

   

   

    function smtp_sockopen($address)    

   

   

    {    

   

   

        if ($this->relay_host == "") {    

   

   

            return $this->smtp_sockopen_mx($address);    

   

   

        } else {    

            return $this->smtp_sockopen_relay();    

        }    

    }    

    function smtp_sockopen_relay()    

    {    

        $this->log_write("Trying to ".$this->relay_host.":".$this->smtp_port."\n");    

        $this->sock = @fsockopen($this->relay_host, $this->smtp_port, $errno, $errstr, $this->time_out);    

        if (!($this->sock && $this->smtp_ok())) {    

            $this->log_write("Error: Cannot connenct to relay host ".$this->relay_host."\n");    

            $this->log_write("Error: ".$errstr." (".$errno.")\n");    

            return FALSE;    

        }    

        $this->log_write("Connected to relay host ".$this->relay_host."\n");    

        return TRUE;    

    }    

    function smtp_sockopen_mx($address)    

    {    

        $domain = ereg_replace("^.+@([^@]+)$", "\1", $address);    

        if (!@getmxrr($domain, $MXHOSTS)) {    

            $this->log_write("Error: Cannot resolve MX \"".$domain."\"\n");    

            return FALSE;    

        }    

        foreach ($MXHOSTS as $host) {    

            $this->log_write("Trying to ".$host.":".$this->smtp_port."\n");    

           $this->sock = @fsockopen($host, $this->smtp_port, $errno, $errstr, $this->time_out);    

            if (!($this->sock && $this->smtp_ok())) {    

                $this->log_write("Warning: Cannot connect to mx host ".$host."\n");    

                $this->log_write("Error: ".$errstr." (".$errno.")\n");    

               continue;    

            }    

            $this->log_write("Connected to mx host ".$host."\n");    

            return TRUE;    

        }    

        $this->log_write("Error: Cannot connect to any mx hosts (".implode(", ", $MXHOSTS).")\n");    

       return FALSE;    

    }    

    function smtp_message($header, $body)    

    {    

      fputs($this->sock, $header."\r\n".$body);    

        $this->smtp_debug("> ".str_replace("\r\n", "\n"."> ", $header."\n> ".$body."\n> "));    

        return TRUE;    

    }    

    function smtp_eom()    

   {    

        fputs($this->sock, "\r\n.\r\n");    

        $this->smtp_debug(". [EOM]\n");    

        return $this->smtp_ok();    

    }    

    function smtp_ok()    

   {    

        $response = str_replace("\r\n", "", fgets($this->sock, 512));    

        $this->smtp_debug($response."\n");    

        if (!ereg("^[23]", $response)) {    

            fputs($this->sock, "QUIT\r\n");    

            fgets($this->sock, 512);    

            $this->log_write("Error: Remote host returned \"".$response."\"\n");    

            return FALSE;    

        }    

        return TRUE;    

    }    

    function smtp_putcmd($cmd, $arg = "")    

    {    

        if ($arg != "") {    

           if($cmd=="") $cmd = $arg;    

            else $cmd = $cmd." ".$arg;    

        }    

        fputs($this->sock, $cmd."\r\n");    

        $this->smtp_debug("> ".$cmd."\n");    

        return $this->smtp_ok();    

    }    

    function smtp_error($string)    

    {    

        $this->log_write("Error: Error occurred while ".$string.".\n");    

        return FALSE;    

    }    

    function log_write($message)    

    {    

        $this->smtp_debug($message);    

        if ($this->log_file == "") {    

                return TRUE;    

        }    

        $message = date("M d H:i:s ").get_current_user()."[".getmypid()."]: ".$message;    

        if (!@file_exists($this->log_file) || !($fp = @fopen($this->log_file, "a"))) {    

            $this->smtp_debug("Warning: Cannot open log file \"".$this->log_file."\"\n");    

            return FALSE;;    

        }    

        flock($fp, LOCK_EX);    

        fputs($fp, $message);    

        fclose($fp);    

        return TRUE;    

    }    

    function strip_comment($address)    

   {    

        $comment = "\([^()]*\)";    

       while (ereg($comment, $address)) {    

            $address = ereg_replace($comment, "", $address);    

        }    

        return $address;    

    }    

    function get_address($address)    

    {    

        $address = ereg_replace("([ \t\r\n])+", "", $address);    

        $address = ereg_replace("^.*<(.+)>.*$", "\1", $address);    

        return $address;    

    }    

    function smtp_debug($message)    

    {    

        if ($this->debug) {    

        echo $message;    

        }    

    }    

}    

?> 

//发送邮件程序mail.php

<?    

//使用方法    

require("smtp.class.php");    

$smtpserver = "mail1.baicai.cn";//SMTP服务器    

$smtpserverport =25;//SMTP服务器端口    

$smtpusermail = "service@mail1.baicai.cn";//SMTP服务器的用户邮箱    

$smtpemailto = "406289733@qq.com";//发送给谁    

$smtpuser = "service@mail.163.cn";//SMTP服务器的用户帐号    

$smtppass = "service";//SMTP服务器的用户密码    

$mailsubject = "php邮件发送成功";//邮件主题    

$mailbody = "<h1>测试邮件的内容</h1>";//邮件内容    

$mailtype = "HTML";//邮件格式(HTML/TXT,TXT为文本邮件    

$smtp = new smtp($smtpserver,$smtpserverport,true,$smtpuser,$smtppass);//这里面的一个true是表示使用身份验证,否则不使用身份验证.    

$smtp->debug = TRUE;//是否显示发送的调试信息    

$smtp->sendmail($smtpemailto, $smtpusermail, $mailsubject, $mailbody, $mailtype);    

?>

 

 

扩展:本文的邮件系统可以与计划任务(crond)来结合,定期发送邮件,来检查邮件系统是否正常。

 

源文档 <http://zhongxm2007.blog.163.com/blog/static/2630077420099183738126/

 

 

 

php获取google当前天气实现程序

2013年10月16日

2:42

程>>Php应用 >文章内容 

 

php获取google当前天气实现程序

 

www.111cn.net  2013-01-06  编辑:future 

 

 

 

我们会看到很多网站都可以实时的显示当时当地的天气,下面我来告诉你这种实时天气的做吧,利用google aip接口即可实现获取不同城市的天气并显示在自己网站上。

更多详细内容请查看:http://www.111cn.net/phper/php/44965.htm

 

 

 

se.php

 

 

 

 代码如下 复制代码 

 

<?php

 $city = $_GET['city'];

 $data = createXml($city);

  

 $xml = simplexml_load_string($data);

 header("Content-type: text/xml");

 echo $xml->asXML();

  

 // 生成XML数据

function createXml($city)

 {

     // Google 天气API

     $weather = simplexml_load_file("http://www.google.com/ig/api?weather={$city}");

     if(isset($weather->weather->forecast_conditions))

     {

         $low = f2c($weather->weather->forecast_conditions->low['data']);

         $high = f2c($weather->weather->forecast_conditions->high['data']);

         return "<weather>n<city>{$city}</city>n<low>{$low}</low>n<high>{$high}</high></weather>n";

     }

     else

     {

         return "<weather>n</weather>n";

     }

 }

  

 // 华氏度转摄氏度

function f2c($fahrenhite)

 {

     return floor(($fahrenhite - 32) / 1.8);

 }

 

 

 

 

 

客户端 c.php

 

 

 

 代码如下 复制代码 

<html>

 <head>

 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

 <title>天气查询</title>

 </head>

 <body>

 <form method="post" action="">

 <select name="city">

 <option value="0">请选择</option>

 <option value="beijing">北京</option>

 <option value="shanghai">上海</option>

 <option value="guangzhou">广州</option>

 <option value="wuhan">武汉</option>

 </select>

 <input type="submit" />

 </form>

  

 <?php

 if(!empty($_POST['city']))

 {

     $city = $_POST['city'];

     $xml = simplexml_load_file("http://127.0.0.1/rest/se.php?city={$city}");

     $html = "<p>City:{$xml->city}</p>n";

     $html .= "<p>Low:{$xml->low}</p>n";

     $html .= "<p>High:{$xml->high}</p>n";

     echo $html;

 }

 ?>

 </body>

 </html>  

 

更多详细内容请查看:http://www.111cn.net/phper/php/44965.htm

 

 

 

2013年10月16日

2:44

PHP获取本地天气预报信息

php获取本地天气,思路:获取本地ip地址,使用curl函数获取新浪天气信息,输出天气预报信息。

代码如下:

<html>
  <head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body >
         
<?php
/*
*Des:php天气预报
*Author:Harry
*URL:http://luozhenkun.diandian.com
*
*/
 // 复杂获取本地ip地址
/* if (getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP'), 'unknown')) {
    $SA_IP = getenv('HTTP_CLIENT_IP');
} elseif (getenv('HTTP_X_FORWARDED_FOR') && strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), 'unknown')) {
    $SA_IP = getenv('HTTP_X_FORWARDED_FOR');
} elseif (getenv('REMOTE_ADDR') && strcasecmp(getenv('REMOTE_ADDR'), 'unknown')) {
    $SA_IP = getenv('REMOTE_ADDR');
} elseif (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown')) {
    $SA_IP = $_SERVER['REMOTE_ADDR'];
} */
$SA_IP=$_SERVER['REMOTE_ADDR'];//简单获取本地ip地址
//定义一个函数根据ip获取城市名,使用新浪的天气预报
function getIPLoc_sina($queryIP){
    $url = 'http://int.dpool.sina.com.cn/iplookup/iplookup.php?format=json&ip=' . $queryIP;
    $ch  = curl_init($url);//初始化url地址
    curl_setopt($ch, CURLOPT_ENCODING, 'utf8');//设置一个cURL传输选项
    curl_setopt($ch, CURLOPT_TIMEOUT, 10);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 获取数据返回 
    $location = curl_exec($ch);//执行一个cURL会话
    $location = json_decode($location);//对 JSON 格式的字符串进行编码
    curl_close($ch);//关闭一个cURL会话
    $loc = "";
    if ($location === FALSE)
        return "";
    if (empty($location->desc)) {
        $loc      = $location->city;
        $full_loc = $location->province . $location->city . $location->district . $location->isp;
    } else {
        $loc = $location->desc;
    }
    return $loc;
}
$city     = getIPLoc_sina("$SA_IP");
        
$citycode = mb_convert_encoding($city, "gb2312", "utf-8");
        
$doc      = new DOMDocument();
if (!@$doc->load("http://php.weather.sina.com.cn/xml.php?city=" . $citycode . "&password=DJOYnieT8234jlsK&day=0")) {
    echo "Get data failed!!\n";
    return;
}
         
$city         = $doc->getElementsByTagName("city")->item(0)->nodeValue;
$stat1        = $doc->getElementsByTagName("status1")->item(0)->nodeValue;
$stat2        = $doc->getElementsByTagName("status2")->item(0)->nodeValue;
$tmp1         = $doc->getElementsByTagName("temperature1")->item(0)->nodeValue;
$tmp2         = $doc->getElementsByTagName("temperature2")->item(0)->nodeValue;
$date         = $doc->getElementsByTagName("savedate_weather")->item(0)->nodeValue;
$weather_info = "$date $city $stat1~$stat2 ";
echo $weather_info . $tmp1 . "℃~" . $tmp2 . "℃";
?>
 <body>
</html>

 

源文档 <http://luozhenkun.diandian.com/post/2012-08-22/40038565845

 

 

 

mysql 高级

2013年10月15日

17:29

 

1、视图view

2、触发器trigger

3、存储过程procddure************

4、sql编程*************

5、索引************

6、存储引擎************

7、事务****************

*号的是一定得掌握的

 

 

设计数据库

2013年10月16日

10:29

 

1、建表

2、建表:字段、数据类型、约束、表关系、索引、存储引擎

3、触发器、存储过程:sql编程、事务

4、视图

5、检查:整个数据的合理性(数据是否合理,使用是否方便)、重复的字段

 

 

在有外键的表上进行truncate---->

2013年10月19日

4:39

 

TRUNCATE】在有外键参照的表上无法使用TRUNCATE完成数据清理(ORA-02266

上一篇 / 下一篇  2010-06-10 23:09:27 / 个人分类:故障处理与分析 

查看( 1129 ) / 评论( 2 ) / 评分( 10 / 0 ) 

众所周知,使用TRUNCATE方法可以非常快速的完成数据清理的任务,但在具有外键参照的表上不可以简简单单的完成TRUNCATE的任务。

在具有外键参照的表上完成TRUNCATE操作会收到报错信息“ORA-02266: unique/primary keys in table referenced by enabled foreign keys”

 

简单模拟一下这个报错过程及处理方法。

 

1.创建主外键参照表中的主表T_PARENT并初始化数据

sys@ora10g> conn sec/sec

Connected.

sec@ora10g> create table t_parent (parent_id int primary key, name varchar2(10));

 

Table created.

 

sec@ora10g> insert into t_parent values (1,'secooler1');

 

1 row created.

 

sec@ora10g> insert into t_parent values (2,'secooler2');

 

1 row created.

 

sec@ora10g> insert into t_parent values (3,'secooler3');

 

1 row created.

 

sec@ora10g> commit;

 

Commit complete.

 

sec@ora10g> select * from t_parent;

 

 PARENT_ID NAME

---------- ------------------------------

         1 secooler1

         2 secooler2

         3 secooler3

 

3 rows selected.

 

2.此时T_PARENT在没有外键参照的情况下是可以完成TRUNCATE操作的

sec@ora10g> truncate table t_parent;

 

Table truncated.

 

sec@ora10g> select * from t_parent;

 

no rows selected

 

3.创建参照主表T_PARENT的子表T_CHILD

sec@ora10g> create table t_child (child1_id int primary key, parent_id int);

 

Table created.

 

sec@ora10g> alter table t_child add constraint FK_t_child foreign key (parent_id) references t_parent (parent_id) on delete cascade;

 

Table altered.

 

sec@ora10g> insert into t_child values (1,1);

 

1 row created.

 

sec@ora10g> commit;

 

Commit complete.

 

sec@ora10g> select * from t_child;

 

 CHILD1_ID  PARENT_ID

---------- ----------

         1          1

 

4.此时如在具有外键参照的T_PARENT表上使用TRUNCATE命令将无法完成

sec@ora10g> truncate table t_parent;

truncate table t_parent

               *

ERROR at line 1:

ORA-02266: unique/primary keys in table referenced by enabled foreign keys

 

5.处理方法

根本原因是因为外键约束导致的,因此,如果执意要使用TRUNCATE完成数据的清理(知道操作的后果),仅需将约束disable即可。

sec@ora10g> alter table t_child disable constraint FK_t_child;

 

Table altered.

 

sec@ora10g> truncate table t_parent;

 

Table truncated.

 

6.小结

从约束完整性上考虑,在数据量比较少的情况下应该尽量使用delete方法进行数据清理。

但是,当数据量达到一定程度时,也许迫不得已必须使用TRUNCATE方法来完成数据的快速清理。在知道TRUNCATE后果的前提下它是一个非常优秀的工具。

 

Good luck.

 

secooler

10.06.10

 

-- The End --

 

源文档 <http://space.itpub.net/519536/viewspace-664961

 

 

 

一些细节

20131116

17:33

 

cdutyang:以上楼上的讲解还是不太明白。。。ENGINE=InnoDB  DEFAULT CHARSET=gbk AUTO_INCREMENT=5 ;为什么这几句是括号外边呢?新手。。

 (2012-02-19 20:47) 

 

因为这句话描述的是table本身的信息而不是内部字段的信息 

 

来自 <http://bbs.php100.com/read-htm-tid-7597.html

 

 

 

 

 

 

 AUTO_INCREMENT=5  表示自增从5开始往后自增

 

ID编号从5开始 

 

notepad++       写数据库,是个不错的选择

创建sql文件,再用notepad++编辑,它会有很好的提示

 

 

phpMyadmin

20131119

1:08

 

PHPmyadmin密码设置

2013-04-15 13:10 达内

 

 

PHPmyadmin密码怎样设置那,有很多人都想知识答案,今天达内IT培训为大家简述PHPmyadmin密码设置的方法,希望打家喜欢。打开PHPMyAdmin中libraries文件找到config.default.php并打开.

 

  找到$cfg[‘servers’] [$i] [‘user’] = ' ',在' '中加入'root'

 

  找到$cfg[‘servers’] [$i] [‘password’] = ' ',在' '中加入'123456';

 

  这两个地方的修改就是加入刚才安装的MySQL的用户名和密码,读者可自行修改.

0 0
原创粉丝点击