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
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");
?>
$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 = ' ';'.$row["title"].'('.$row["page_time"].')'.'
echo $line;
printf("\n");
}
mysql_free_result($result);
?>
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 中名称概念 .( 如上图 )
1 ) Sql 结点( SQL node-- 上图对应为 mysqld ) : 分布式数据库。包括自身数据和查询中心结点数据 .
2 )数据结点 (Data node -- ndbd): 集群共享数据 ( 内存中 ).
3 )管理服务器 (Management Server – ndb_mgmd): 集群管理 SQL node,Data node.
3 .配置
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
//发送邮件的类
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
}
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 = "[email protected]";//SMTP服务器的用户邮箱
$smtpemailto = "[email protected]";//发送给谁
$smtpuser = "[email protected]";//SMTP服务器的用户帐号
$smtppass = "service";//SMTP服务器的用户密码
$mailsubject = "php邮件发送成功";//邮件主题
$mailbody = "测试邮件的内容
";//邮件内容
$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
代码如下 复制代码
$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 "
}
else
{
return "
}
}
// 华氏度转摄氏度
function f2c($fahrenhite)
{
return floor(($fahrenhite - 32) / 1.8);
}
客户端 c.php
代码如下 复制代码
if(!empty($_POST['city']))
{
$city = $_POST['city'];
$xml = simplexml_load_file("http://127.0.0.1/rest/se.php?city={$city}");
$html = " City:{$xml->city}
$html .= " Low:{$xml->low}
$html .= " High:{$xml->high}
echo $html;
}
?>
更多详细内容请查看:http://www.111cn.net/phper/php/44965.htm
2013年10月16日
2:44
PHP获取本地天气预报信息
php获取本地天气,思路:获取本地ip地址,使用curl函数获取新浪天气信息,输出天气预报信息。
代码如下:
/*
*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 . "℃";
?>
源文档 <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>
一些细节
2013年11月16日
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
2013年11月19日
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的用户名和密码,读者可自行修改.