<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>71街 &#187; mysql</title>
	<atom:link href="http://www.71j.cn/archives/tag/mysql/feed" rel="self" type="application/rss+xml" />
	<link>http://www.71j.cn</link>
	<description>杜工的技术博客</description>
	<lastBuildDate>Fri, 16 Dec 2011 03:52:13 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>杜工在windows下定时备份mysql的脚本</title>
		<link>http://www.71j.cn/archives/288</link>
		<comments>http://www.71j.cn/archives/288#comments</comments>
		<pubDate>Mon, 12 Dec 2011 12:32:03 +0000</pubDate>
		<dc:creator>杜工</dc:creator>
				<category><![CDATA[感悟]]></category>
		<category><![CDATA[mysql]]></category>

		<guid isPermaLink="false">http://www.71j.cn/?p=288</guid>
		<description><![CDATA[嘿嘿，大家是不是经常为找不到windows下的定时备份脚本而苦恼（哭闹？），这里杜工分享下bat脚本做自动备份的例子，使用前请先安装WinRAR。 rem rem C:\Program Files &#40;x86&#41;\WinRAR 需要配置到系... ]]></description>
			<content:encoded><![CDATA[<p>嘿嘿，大家是不是经常为找不到windows下的定时备份脚本而苦恼（哭闹？），这里杜工分享下bat脚本做自动备份的例子，使用前请先安装WinRAR。</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">rem
rem C:\Program Files <span style="color: #66cc66;">&#40;</span>x86<span style="color: #66cc66;">&#41;</span>\WinRAR 需要配置到系统环境变量 path 下，才能调用rar cli工具
rem
rem 跳转到工作目录下
e:
cd e:\DBBAK
rem 设置备份文件名
<span style="color: #993333; font-weight: bold;">SET</span> BAK_FILE<span style="color: #66cc66;">=</span>MY_DBBAK_%<span style="color: #993333; font-weight: bold;">DATE</span>:~<span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,-</span><span style="color: #cc66cc;">4</span>%<span style="color: #66cc66;">.</span><span style="color: #993333; font-weight: bold;">SQL</span>
rem 设置日志文件名
<span style="color: #993333; font-weight: bold;">SET</span> LOG_FILE<span style="color: #66cc66;">=</span>MY_DBBAK<span style="color: #66cc66;">.</span>log
rem 记录日志
echo <span style="color: #ff0000;">&quot;%date%&quot;</span> <span style="color: #66cc66;">&gt;&gt;</span> %LOG_FILE%
rem 开始dump
mysqldump <span style="color: #808080; font-style: italic;">--default-character-set=utf8 -hlocalhost -uroot -R --triggers --single-transaction -B mydb &gt; %BAK_FILE%</span>
rem 压缩备份文件
rar a %BAK_FILE%<span style="color: #66cc66;">.</span>rar %BAK_FILE%
rem 删除临时文件
del <span style="color: #66cc66;">/</span>F %BAK_FILE%
echo <span style="color: #ff0000;">&quot;%date%&quot;</span> <span style="color: #66cc66;">&gt;&gt;</span> %LOG_FILE%
echo <span style="color: #ff0000;">&quot;&quot;</span> <span style="color: #66cc66;">&gt;&gt;</span> %LOG_FILE%</pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://www.71j.cn/archives/288/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mysql服务无法启动,错误1067最快解决办法</title>
		<link>http://www.71j.cn/archives/280</link>
		<comments>http://www.71j.cn/archives/280#comments</comments>
		<pubDate>Tue, 01 Nov 2011 03:56:55 +0000</pubDate>
		<dc:creator>杜工</dc:creator>
				<category><![CDATA[感悟]]></category>
		<category><![CDATA[mysql]]></category>

		<guid isPermaLink="false">http://www.71j.cn/?p=280</guid>
		<description><![CDATA[mysql 1067错误一般出现在windows系统下，自定义data目录路径的时候。即使是最新的mysql5.5 安装包，在安装完成进行配置时，也会出现这个问题。 杜工解决方法：将data目录设置在mysql安装目录下，... ]]></description>
			<content:encoded><![CDATA[<p>mysql 1067错误一般出现在windows系统下，自定义data目录路径的时候。即使是最新的mysql5.5 安装包，在安装完成进行配置时，也会出现这个问题。</p>
<p>杜工解决方法：将data目录设置在mysql安装目录下，可正常启动服务。</p>
<p>过程：安装msi文件，到最后一步配置时，可跳过，然后进入安装目录 /bin/下，找到MysqlInstanceConfig.exe，运行后，可按照提示一步一步配置。</p>
<p><a href="http://www.71j.cn/wp-content/uploads/2011/11/QQ截图20111101115650.jpg"><img class="aligncenter size-full wp-image-281" title="mysql config application" src="http://www.71j.cn/wp-content/uploads/2011/11/QQ截图20111101115650.jpg" alt="" width="825" height="374" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.71j.cn/archives/280/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>configure: error: Cannot find MySQL header files under yes.杜工解决办法</title>
		<link>http://www.71j.cn/archives/251</link>
		<comments>http://www.71j.cn/archives/251#comments</comments>
		<pubDate>Tue, 19 Apr 2011 17:44:57 +0000</pubDate>
		<dc:creator>杜工</dc:creator>
				<category><![CDATA[感悟]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.71j.cn/?p=251</guid>
		<description><![CDATA[CentOS或者redhad下用yum或者rpm安装了 mysql 及 mysql-server , 在编译安装php时用 &#8211;with-mysql 选项出现错误 Note that the MySQL client library is not bundled anymore. 首先使用命令find / -name &#8216;mysql.h’ 查找路径... ]]></description>
			<content:encoded><![CDATA[<p>CentOS或者redhad下用yum或者rpm安装了 mysql 及 mysql-server , 在编译安装php时用 &#8211;with-mysql 选项出现错误</p>
<p>Note that the MySQL client library is not bundled anymore.</p>
<p>首先使用命令find / -name &#8216;mysql.h’ 查找路径，如果找到就给with-mysql=赋上路径，如果找不到，那就是缺少了 mysql-devel 安装包，用yum或者rpm安装上，即可解决问题</p>
]]></content:encoded>
			<wfw:commentRss>http://www.71j.cn/archives/251/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>如何去管理php的用户名和密码(二)</title>
		<link>http://www.71j.cn/archives/183</link>
		<comments>http://www.71j.cn/archives/183#comments</comments>
		<pubDate>Thu, 17 Jun 2010 06:32:25 +0000</pubDate>
		<dc:creator>杜工</dc:creator>
				<category><![CDATA[感悟]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[密码]]></category>
		<category><![CDATA[用户名]]></category>
		<category><![CDATA[预备语句]]></category>

		<guid isPermaLink="false">http://71j.cn/?p=183</guid>
		<description><![CDATA[(接上文:http://71j.cn/archives/173) 操练开始 在我们做出测试代码之前，首先要创建一个用户数据表。运行如下语句： create database myapp; use myapp; create table users &#40;user varchar&#40;60&#41;, pass varchar&#40;60&#... ]]></description>
			<content:encoded><![CDATA[<p>(接上文:<a href="http://71j.cn/archives/173">http://71j.cn/archives/173</a>)</p>
<p><strong>操练开始</strong><strong></strong></p>
<p>在我们做出测试代码之前，首先要创建一个用户数据表。运行如下语句：</p>

<div class="wp_syntax"><div class="code"><pre class="mysql" style="font-family:monospace;"><span style="color: #990099; font-weight: bold;">create</span> <span style="color: #990099; font-weight: bold;">database</span> myapp<span style="color: #000033;">;</span>
<span style="color: #990099; font-weight: bold;">use</span> myapp<span style="color: #000033;">;</span>
<span style="color: #990099; font-weight: bold;">create</span> <span style="color: #990099; font-weight: bold;">table</span> users <span style="color: #FF00FF;">&#40;</span><span style="color: #000099;">user</span> <span style="color: #999900; font-weight: bold;">varchar</span><span style="color: #FF00FF;">&#40;</span><span style="color: #008080;">60</span><span style="color: #FF00FF;">&#41;</span><span style="color: #000033;">,</span> pass <span style="color: #999900; font-weight: bold;">varchar</span><span style="color: #FF00FF;">&#40;</span><span style="color: #008080;">60</span><span style="color: #FF00FF;">&#41;</span><span style="color: #FF00FF;">&#41;</span><span style="color: #000033;">;</span></pre></div></div>

<p>其中user用来储存用户名，pass用来储存密码的hash值。目前，phpass生成的密码hash值最大长度为60。</p>
<p><strong>创建新用户</strong><strong></strong></p>
<p>首先，我们从phpass项目网站把<em>P</em>asswordHash.php下载到网站目录中，并设置能让php加载的权限（Unix系统下一般为600或者644）。然后在网站目录中创建两个文件：user-man.html (644权限), and user-man.php (权限同asswordHash.php)。</p>
<p>下面，把下面的内容写在user-man.html中：</p>

<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">form</span> <span style="color: #000066;">action</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;user-man.php&quot;</span> <span style="color: #000066;">method</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;POST&quot;</span>&gt;</span>
用户名:<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">br</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">size</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;60&quot;</span>&gt;&lt;<span style="color: #000000; font-weight: bold;">br</span>&gt;</span>
密码：<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">br</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">size</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;60&quot;</span>&gt;&lt;<span style="color: #000000; font-weight: bold;">br</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;创建新用户&quot;</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">form</span>&gt;</span></pre></div></div>

<p>这个文件获取用户名和密码，然后提交到user-man.php。下面是user-man.php的代码：</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Content-Type: text/plain'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// 本例只是简单的输出文本的hash值，所以开头要声明下，不让浏览器当作html解析。</span>
&nbsp;
 
&nbsp;
<span style="color: #b1b100;">require</span> <span style="color: #0000ff;">'../PasswordHash.php'</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Base-2 logarithm of the iteration count used for password stretching</span>
<span style="color: #000088;">$hash_cost_log2</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">8</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">// Do we require the hashes to be portable to older systems (less secure)?</span>
<span style="color: #000088;">$hash_portable</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">FALSE</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//在实际应用中，上面两行最好写在配置文件中，比如config.inc.php</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//下面开始获取提交的用户名和密码，实际应用中需要验证有效性，不再赘述。</span>
&nbsp;
<span style="color: #000088;">$user</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$_POST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'user'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$pass</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$_POST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'pass'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//下面开始计算密码hash值</span>
&nbsp;
<span style="color: #000088;">$hasher</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> PasswordHash<span style="color: #009900;">&#40;</span><span style="color: #000088;">$hash_cost_log2</span><span style="color: #339933;">,</span> <span style="color: #000088;">$hash_portable</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$hash</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$hasher</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">HashPassword</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$pass</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">strlen</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$hash</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&lt;</span> <span style="color: #cc66cc;">20</span><span style="color: #009900;">&#41;</span><span style="color: #666666; font-style: italic;">//这里用的CRYPT_EXT_DES方法，其它加密算法得到结果会更长。</span>
    fail<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Failed to hash new password'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">unset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$hasher</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> fail<span style="color: #009900;">&#40;</span><span style="color: #000088;">$pub</span><span style="color: #339933;">,</span> <span style="color: #000088;">$pvt</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$msg</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$pub</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$pvt</span> <span style="color: #339933;">!==</span> <span style="color: #0000ff;">''</span><span style="color: #009900;">&#41;</span>
        <span style="color: #000088;">$msg</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">&quot;: <span style="color: #006699; font-weight: bold;">$pvt</span>&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #990000;">exit</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;An error occurred (<span style="color: #006699; font-weight: bold;">$msg</span>).<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//下面开始把用户信息存入到数据库中</span>
&nbsp;
<span style="color: #000088;">$db_host</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'localhost'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$db_port</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">3306</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$db_user</span> <span style="color: #339933;">=</span> ‘dbuser’<span style="color: #339933;">;</span>
<span style="color: #000088;">$db_pass</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'dbpass'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$db_name</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'dbname'</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//数据库信息也最好存储在配置文件中。下面开始连接数据库，并注意弹出失败信息。</span>
&nbsp;
<span style="color: #000088;">$db</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> mysqli<span style="color: #009900;">&#40;</span><span style="color: #000088;">$db_host</span><span style="color: #339933;">,</span> <span style="color: #000088;">$db_user</span><span style="color: #339933;">,</span> <span style="color: #000088;">$db_pass</span><span style="color: #339933;">,</span> <span style="color: #000088;">$db_name</span><span style="color: #339933;">,</span> <span style="color: #000088;">$db_port</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">mysqli_connect_errno</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
    fail<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'MySQL connect'</span><span style="color: #339933;">,</span> <span style="color: #990000;">mysqli_connect_error</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//下面用预备语句插入用户信息</span>
&nbsp;
<span style="color: #009900;">&#40;</span><span style="color: #000088;">$stmt</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">prepare</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'insert into users (user, pass) values (?, ?)'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #339933;">||</span> fail<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'MySQL prepare'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">error</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$stmt</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">bind_param</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'ss'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$user</span><span style="color: #339933;">,</span> <span style="color: #000088;">$hash</span><span style="color: #009900;">&#41;</span>
    <span style="color: #339933;">||</span> fail<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'MySQL bind_param'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">error</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$stmt</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">execute</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #339933;">||</span> fail<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'MySQL execute'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">error</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//最后数据库连接</span>
&nbsp;
<span style="color: #000088;">$stmt</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">close</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">close</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>好了，把左右文件保存好，放在web server下测试下。输入用户名和密码，提交后，到数据库中看下：</p>
<p>mysql&gt; select * from users;<br />
+&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+<br />
| user   |pass                                                         |<br />
+&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+<br />
| myuser | $3b$08$Lg5XF1Tr.X5TGyfb43vBBeEFZm4GTRQhKQ6SY6emkcnhAGT8KfxFS |<br />
+&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+<br />
1 row in set (0.00 sec)</p>
<p>至此，用户插入成功。</p>
<p>用户已经存在</p>
<p>下面，我们用上面的方法插入一个相同的用户，同时，用相同的密码。然后查看数据库：</p>
<p>mysql&gt; select * from users;<br />
+&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+<br />
| user   |pass                                                         |<br />
+&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+<br />
| myuser | $3b$08$Lg5XF1Tr.X5TGyfb43vBBeEFZm4GTRQhKQ6SY6emkcnhAGT8KfxFS |<br />
| myuser | $1a$08$7lM07FwQMm5/C8G/urT4z..MudfsS227e8oUEu6T51bNWk/RGb/qe |<br />
+&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+<br />
2 rows in set (0.00 sec)</p>
<p>我们得到了用户名相同的两条记录，但是密码hash值不相同，虽然我们使用了相同的密码。</p>
<p>为了解决这个问题，我们可以在执行插入前先执行一个select语句，查询下该用户名是否已经存在了。但是，这对程序的效率来说不是最优化的。好的做法是让为用户名建立唯一索引，禁止用户用户名的出现：</p>

<div class="wp_syntax"><div class="code"><pre class="mysql" style="font-family:monospace;"><span style="color: #990099; font-weight: bold;">DROP</span> <span style="color: #990099; font-weight: bold;">TABLE</span> users<span style="color: #000033;">;</span>
<span style="color: #990099; font-weight: bold;">CREATE</span> <span style="color: #990099; font-weight: bold;">TABLE</span> users <span style="color: #FF00FF;">&#40;</span><span style="color: #000099;">user</span> <span style="color: #999900; font-weight: bold;">varchar</span><span style="color: #FF00FF;">&#40;</span><span style="color: #008080;">60</span><span style="color: #FF00FF;">&#41;</span><span style="color: #000033;">,</span> pass <span style="color: #999900; font-weight: bold;">varchar</span><span style="color: #FF00FF;">&#40;</span><span style="color: #008080;">60</span><span style="color: #FF00FF;">&#41;</span><span style="color: #000033;">,</span> <span style="color: #FF9900; font-weight: bold;">UNIQUE</span> <span style="color: #FF00FF;">&#40;</span><span style="color: #000099;">user</span><span style="color: #FF00FF;">&#41;</span><span style="color: #FF00FF;">&#41;</span><span style="color: #000033;">;</span></pre></div></div>

<p>当我们插入相同的用户名时，程序就会报错：</p>
<p>An error occurred (MySQL execute: Duplicate entry &#8216;myuser&#8217; for key 1).</p>
<p>如此，系统效率会得到提高。虽然，这是纯技术性的错误提示， 我们将稍侯予以解决。</p>
<p><strong>避免泄漏过多服务器细节</strong></p>
<p>上面出现的报错多是mysql服务器报错，可能会泄漏一些敏感信息，如数据库名，数据库地址，甚至数据表文件的存储地址都会被显示，这是很危险的。因此，这些信息我们并不希望被显示，除非我们就是用户，或者是在调试。如此，我们可以修改fail()函数，把错误信息显示为用户可见的内容。</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// 是否为debug模式，如果是，会显示敏感信息。</span>
<span style="color: #000088;">$debug</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">TRUE</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> fail<span style="color: #009900;">&#40;</span><span style="color: #000088;">$pub</span><span style="color: #339933;">,</span> <span style="color: #000088;">$pvt</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">global</span> <span style="color: #000088;">$debug</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$msg</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$pub</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$debug</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #000088;">$pvt</span> <span style="color: #339933;">!==</span> <span style="color: #0000ff;">''</span><span style="color: #009900;">&#41;</span>
        <span style="color: #000088;">$msg</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">&quot;: <span style="color: #006699; font-weight: bold;">$pvt</span>&quot;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">/* $pvt 可能会含有敏感信息，比如需要隐藏掉，或者需要编码才能被html正确显示的内容。*/</span>
    <span style="color: #990000;">exit</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;An error occurred (<span style="color: #006699; font-weight: bold;">$msg</span>).<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>需要注意的，不管是apache还是php，默认情况下是会显示所有调试信息的。所以，作为一个程序员，我们的职责是防止这些信息被泄漏，就跟我们设置了debug模式一样，这对程序员或者服务器运维人员来说至关重要。默认情况下，要把$debug值设置为false，但我们的例子作为测试来说，将继续使用true.</p>
<p><strong>如何区分mysql</strong><strong>报错</strong></p>
<p>我们需要去辨别mysql报错，以确定用户是否已经存在于数据库中，如果已经存在，需要输出一个友好的错误提示。因为当我们插入用户的时候，不只是会有一种错误，当出现其它错误的时候，我们不能傻不愣瞪的提示相同的错误（用户已经存在）吧？</p>
<p>一种解决方法是在出现报错后执行一个针对该用户名的select查询，如果能够返回一行数据，说明用户确实一定存在了。实现方法如下：</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$stmt</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">execute</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$save_error</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">error</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$stmt</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">close</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// 用户已经存在了?</span>
    <span style="color: #009900;">&#40;</span><span style="color: #000088;">$stmt</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">prepare</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'select user from users where user=?'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
        <span style="color: #339933;">||</span> fail<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'MySQL prepare'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">error</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$stmt</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">bind_param</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'s'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$user</span><span style="color: #009900;">&#41;</span>
        <span style="color: #339933;">||</span> fail<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'MySQL bind_param'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">error</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$stmt</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">execute</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
        <span style="color: #339933;">||</span> fail<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'MySQL execute'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">error</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$stmt</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">store_result</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
        <span style="color: #339933;">||</span> fail<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'MySQL store_result'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">error</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$stmt</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">num_rows</span> <span style="color: #339933;">===</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span>
        fail<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'This username is already taken'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">else</span>
        fail<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'MySQL execute'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$save_error</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>这个方法确实奏效，而且也很可靠。但是，我们还有更简捷的实现方法，那就是使用mysql错误码：</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$stmt</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">execute</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">errno</span> <span style="color: #339933;">===</span> <span style="color: #cc66cc;">1062</span> <span style="color: #666666; font-style: italic;">/* ER_DUP_ENTRY */</span><span style="color: #009900;">&#41;</span>
        fail<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'额滴神，该用户已经存在了'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">else</span>
        fail<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'MySQL execute'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">error</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>在接下来的例子中，我们将使用这种简单的方法做演示。</p>
<p><strong>魔法引号的处理</strong></p>
<p>Magic quotes 开启后会自动转义输入的数据。其中，所有的单引号（&#8217;）、双引号（”）、反斜线、和 NULL 字符都会被转义（增加个反斜线），其实这操作本质上调用的是 addslashes 函数。</p>
<p>这对程序员来说固然是一个很好的事情，省却了我们过滤的麻烦。但是，当用户输入用户名和密码中含有这些字符时，我们从$_POST中获取到的内容是不是也会被addslashes了呢？</p>
<p>这就需要我们去做判断，示例如下：</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">function</span> get_post_var<span style="color: #009900;">&#40;</span><span style="color: #000088;">$var</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$val</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$_POST</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$var</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">get_magic_quotes_gpc</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
        <span style="color: #000088;">$val</span> <span style="color: #339933;">=</span> <span style="color: #990000;">stripslashes</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$val</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$val</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>接下来，我们将用这个函数取post过来的数据，而不是单纯的$_POST数组。<span id="_marker"> </span></p>
<p><span>(待续)</span></p>
]]></content:encoded>
			<wfw:commentRss>http://www.71j.cn/archives/183/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>如何去管理php的用户名和密码(一)</title>
		<link>http://www.71j.cn/archives/173</link>
		<comments>http://www.71j.cn/archives/173#comments</comments>
		<pubDate>Sun, 13 Jun 2010 09:01:08 +0000</pubDate>
		<dc:creator>杜工</dc:creator>
				<category><![CDATA[感悟]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[密码]]></category>
		<category><![CDATA[用户名]]></category>
		<category><![CDATA[预备语句]]></category>

		<guid isPermaLink="false">http://71j.cn/?p=173</guid>
		<description><![CDATA[目前，多数大型的网站，尤其是SNS社区，都有用户管理系统，这些系统一般都涉及到密码认证的问题。那么这些系统是如何储存用户密码的呢？直接存储密码明文吗？答案是否定的，好的做法... ]]></description>
			<content:encoded><![CDATA[<p>目前，多数大型的网站，尤其是SNS社区，都有用户管理系统，这些系统一般都涉及到密码认证的问题。那么这些系统是如何储存用户密码的呢？直接存储密码明文吗？答案是否定的，好的做法是把密码算出一个哈希(hash)值予以存储。我们会发现好多文章教你怎么去计算密码的hash值，<a href="http://71j.cn">杜工的博客(http://71j.cn)</a>也有类似的文章，不过不是用来加密密码的，只是简单的散列，传统的文章推荐使用md5()，后来有些人推荐把密码连接上一个附加值（我们称之为salt值， Discuz就是这么做的），然后计算sha1()，或者hash()(SHA-256等)，同时把用户名进行mysql_real_escape_string()处理。虽然这些文章介绍的方法总体方向是对的，但是并没有一篇关于密码安全存储的文章是尽善尽美的。</p>
<p>其实，最近的文章已经开始推荐使用<a href="http://www.openwall.com/phpass/" target="_blank">phpass</a>, 这是一个基于php的密码hash算法框架，已经被许多知名的web程序使用，如wordpress、Durpal 7等，但是目前并没有一篇详尽的，一步一步指引我们引用phpass的成型文章，而且密码安全问题，并不只是单纯的如何去hash密码予以存储的问题。</p>
<p>接下来，我将一步步介绍如何把用户密码管理方案引入到一套新的php程序中。首先，将简单阐述密码hash的概念以及如何安全地把这些密码送入数据库，然后通过个示例。从一个简单的创建新用户的程序开始，慢慢展开来，逐渐引入用户登录、修改（重置）密码的功能。</p>
<p>当然，文中会涉及其它相关的概念，如果你已了解，可直接略过。</p>
<p><strong>密码HASH</strong></p>
<p>合格的系统存储在数据库中的并不是密码明文，而是密码hash值。而实际上，单纯的把密码采用php函数，如md5,sha1等，加密后存储，会引发很严重的后果。只要正确的进行了hash，攻击者就很难从获取到的hash值中解析出用户密码，你只需要快速的把弱口令密码解决掉，就能把损失降到最低了。</p>
<p>当用户输入用户名和之前设定好的密码，点击登录进行验证后，程序先要根据用户名查询一些额外信息，如密码哈希类型，salt值，哈希重复的次数等，然后根据这些信息算出密码hash值，与已经存储的hash值进行比较，如果相同，则验证成功。</p>
<p><strong>Salt</strong><strong>方法</strong></p>
<p>Salt是一个近乎随机的字符串，相同的密码使用不同的salt hash散列后， 会得到不同的结果，正确的使用这个方法，可以防止一系列的攻击，包括：</p>
<p>1.通过弱口令（如123456）就知道你的hash类型。</p>
<p>2.使用已经算好的hash值去做比对，如cmd5.com。</p>
<p>3.能够准确知道两个用户（或者一个用户的两个帐号）的密码是否是一样的。</p>
<p>Salt通常和密码hash值储存在一起，它并不是保密的。具体案例可参考<a href="http://hi.baidu.com/ling1026/blog/item/ed2580d39f7ea933970a16c0.html" target="_blank">Ucenter</a></p>
<p><strong>算法强度要提升</strong></p>
<p>一旦密码hash值泄漏 ，攻击者必然会采取暴力破解，一般的hash算法，如md5, sha1等，都是为了保证速度，而非为密码加密准备的，这样势必为攻击者缩短暴力破解提供了可能。因此，采取一个略微复杂点的hash算法，能够降低损失。假想下，如果你的每个密码生成时间家长0.2ms，用户不会有任何不好的体验，但对攻击者来说，这意味着什么？他要多付出几个月甚至几年的时间去破解你的密码！</p>
<p><strong>关于phpass</strong></p>
<p>Phpass是基于php的简单易用的密码hash算法框架。它提供三种hash方法，包括两种基于函数crypt()的&#8212;-CRYPT_BLOWFISH 和 CRYPT_EXT_DES，一种phpass自己的类md5的算法，前者只有php5.30以上的版本支持，后者这是全版本皆可。虽然，所有的算法都使用了salt及算法强度提升的方法，但考虑到效果，我们推荐使用前两种。在使用时，用户可以自定义hash迭代的次数。</p>
<p>在使用的时候，phpass能够自动生成salt和对进行算法拓展，你不需要为生成这些而费神。另外，phpass支持windows系统。</p>
<p><strong>安全的接入数据库</strong></p>
<p><strong>SQL</strong><strong>注入</strong></p>
<p>所谓SQL注入，就是通过把SQL命令（特殊字符串，如单引号等）插入到Web表单递交或输入域名或页面请求的查询字符串，最终达到欺骗服务器执行恶意的SQL命令的行为，比如先前的很多会员网站泄露VIP会员密码大多就是通过WEB表单递交查询字符暴出的，这类表单特别容易受到SQL注入式攻击．</p>
<p><strong>如何防止</strong><strong>SQL</strong><strong>注入</strong><strong></strong></p>
<p>　　1.永远不要信任用户的输入。对用户的输入进行转码校验，可以通过正则表达式，或限制长度；对单引号等特殊字符进行转换，如对数据进行url_encode\ stripslashes等。</p>
<p>　　2.永远不要使用动态拼装sql，可以使用参数化的sql或者直接使用存储过程进行数据查询存取。</p>
<p>　　3.永远不要使用管理员权限的数据库连接，为每个应用使用单独的权限有限的数据库连接。（下面有详细说明）</p>
<p>　　4.不要把机密信息直接存放，加密或者hash掉密码和敏感的信息。</p>
<p>　　5.应用的异常信息应该给出尽可能少的提示，最好使用自定义的错误信息对原始错误信息进行包装。</p>
<p>在接下来的例子中 ，如上几点将得以体现。</p>
<p><strong>组建数据库预备语句</strong><strong></strong></p>
<p>目前，php提供三种连接mysql的接口，一种是自带的，被广泛应用的mysql扩展，另外一种是mysqli扩展， 还有一个PDO(PHP Data Objects)接口，只有mysqli和PDO支持MySQL的<a href="http://dev.mysql.com/tech-resources/articles/4.1/prepared-statements.html" target="_blank">预备语句</a>，而且都需要php5+的支持。本文使用mysqli的方式。</p>
<p>预备语句的使用使数据和代码分离，虽然这并不是最完美的防止sql注入的方法，以为从头到尾，所有的数据都使用相同的socket连接传输，但比传统的语句过滤使用起来更加简单，并且不容易出错。</p>
<p><strong>对数据库采用最小权限原则</strong><strong></strong></p>
<p>除了要预防SQL注入，我们还要预防其它各方面潜在的威胁。好的做法是使用最低权限的数据库帐号，也就是说，不要使用管理员权限的数据库链接，而是为每个应用使用单独的权限的数据库连接。这样，即使你的php代码并不是很“完美”，也可以把网站被攻破而付出最小的代价。</p>
<p>(待续)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.71j.cn/archives/173/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Mysql数据库like模糊查询中文字段不准确的临时解决办法</title>
		<link>http://www.71j.cn/archives/160</link>
		<comments>http://www.71j.cn/archives/160#comments</comments>
		<pubDate>Mon, 19 Apr 2010 09:32:17 +0000</pubDate>
		<dc:creator>杜工</dc:creator>
				<category><![CDATA[感悟]]></category>
		<category><![CDATA[mysql]]></category>

		<guid isPermaLink="false">http://71j.cn/?p=160</guid>
		<description><![CDATA[在mysql下，在进行like检索时，有时候会返回一些与查询词不相关的记录，如查找 “%s%” 时，返回的结果中可能有中文字符，却没有s字符存在，这与数据库中文编码规则有关 如希望查找title中... ]]></description>
			<content:encoded><![CDATA[<p>在mysql下，在进行like检索时，有时候会返回一些与查询词不相关的记录，如查找 “%s%” 时，返回的结果中可能有中文字符，却没有s字符存在，这与数据库中文编码规则有关</p>
<p>如希望查找title中含有字母s的所有新闻：　　</p>

<div class="wp_syntax"><div class="code"><pre class="mysql" style="font-family:monospace;"><span style="color: #990099; font-weight: bold;">select</span> <span style="color: #CC0099;">*</span> <span style="color: #990099; font-weight: bold;">from</span> test.news <span style="color: #990099; font-weight: bold;">where</span> title <span style="color: #CC0099; font-weight: bold;">like</span> <span style="color: #008000;">'<span style="color: #008080; font-weight: bold;">%</span>s<span style="color: #008080; font-weight: bold;">%</span>'</span></pre></div></div>

<p>返回的结果中有一些包含s，而有些则只有中文，很郁闷（也很邪恶，嘿嘿）。</p>
<p>测试了下，发现一种解决方法，就是使用 BINARY（是<a href="cast-functions.html#function_cast"><code>CAST(<em><code>str</code></em> AS BINARY)</code></a>简短写法) 强制转换进行检索</p>

<div class="wp_syntax"><div class="code"><pre class="mysql" style="font-family:monospace;"><span style="color: #990099; font-weight: bold;">select</span> <span style="color: #CC0099;">*</span> <span style="color: #990099; font-weight: bold;">from</span> test.news <span style="color: #990099; font-weight: bold;">where</span> <span style="color: #990099; font-weight: bold;">binary</span> title <span style="color: #CC0099; font-weight: bold;">like</span> <span style="color: #008000;">'<span style="color: #008080; font-weight: bold;">%</span>s<span style="color: #008080; font-weight: bold;">%</span>'</span></pre></div></div>

<p>这样结果就比较准确了，但还有一个问题，就是字母区分大小写，检索的时候依然不正确，只好再转化一下了：</p>

<div class="wp_syntax"><div class="code"><pre class="mysql" style="font-family:monospace;"><span style="color: #990099; font-weight: bold;">select</span> <span style="color: #CC0099;">*</span> <span style="color: #990099; font-weight: bold;">from</span> test.news <span style="color: #990099; font-weight: bold;">where</span> <span style="color: #990099; font-weight: bold;">binary</span> <span style="color: #000099;">ucase</span><span style="color: #FF00FF;">&#40;</span>title<span style="color: #FF00FF;">&#41;</span> <span style="color: #CC0099; font-weight: bold;">like</span>  <span style="color: #008000;">'<span style="color: #008080; font-weight: bold;">%</span>s<span style="color: #008080; font-weight: bold;">%</span>'</span></pre></div></div>

<p>如此，临时解决办法搞定，不过速度会变慢，希望以后的mysql版本能解决掉此问题。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.71j.cn/archives/160/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>浅谈MySQL、Oracle及Postgres中的tablespaces</title>
		<link>http://www.71j.cn/archives/155</link>
		<comments>http://www.71j.cn/archives/155#comments</comments>
		<pubDate>Mon, 22 Mar 2010 06:25:42 +0000</pubDate>
		<dc:creator>杜工</dc:creator>
				<category><![CDATA[感悟]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[oracle]]></category>
		<category><![CDATA[postgres]]></category>
		<category><![CDATA[tablespace]]></category>

		<guid isPermaLink="false">http://71j.cn/?p=155</guid>
		<description><![CDATA[如果你不知道tablespaces(表空间)，你一定会问这到底是NND什么玩意儿，居然会出现在这么多数据库中。其实很简单，tablespaces是为了维持数据库高效运行而附加的一些逻辑条件。 在oracle和mysql中... ]]></description>
			<content:encoded><![CDATA[<p>如果你不知道tablespaces(表空间)，你一定会问这到底是NND什么玩意儿，居然会出现在这么多数据库中。其实很简单，tablespaces是为了维持数据库高效运行而附加的一些逻辑条件。</p>
<p>在oracle和mysql中，tablespaces用来存储一些诸如表和索引的数据段，而在postgres中,一个tablespac是一个物理单元，是一个连接到特定目录的符号连接，它不能运行在不支持符号连接的操作系统，如windows.</p>
<p>实际上，数据文件是oracle和mysql的物理存储机制，虽然postgres也把表数据存在独立文件中，但它支持的表空间非常小。因此，更加合理的把数据分发到磁盘上能够使oracle和mysql的性能更上一层楼, tablespaces正是为了这种合理分发数据方法便于操作而诞生的。</p>
<p>Oracle和mysql创建tablespace的语法基本相同，oracle支持更多的参数，且在一个tablespace允许由多个数据文件组成。下面是一个在mysql下创建和使用tablespace的简单示例：</p>
<pre><strong>mysql&gt; create tablespace myts
-&gt; add datafile 'myfirstfile'
-&gt; engine = falcon;
Query OK, 0 rows affected (0.48 sec)
mysql&gt; create table testmyts (
-&gt; abc integer )
-&gt; tablespace myts;
Query OK, 0 rows affected (0.11 sec)
</strong></pre>
<p>简单说明下，第一条命令是创建一个名字为myts的tablespace, 赋给它的文件名字为myfirstfile，当然我们要使用falcon引擎(<a href="http://www.zxlm.cn/fh/thread-7616-1-1.html" target="_blank">介绍</a>)，运行完这个命令后，就会在mysql数据存储目录中发现一个名为myfirstfile的文件。</p>
<p>第二条命令是用这个tablespace创建一个表，这时候你再看那个tablespace文件，是不是变大了呢？如果没有，向这个表中多插入几条数据再看看。</p>
<p>在oracle中创建表结构，和mysql类似，也很简单：</p>
<pre><strong>SQL&gt; create tablespace myts
 datafile 'myfirstfile'
 size 10M;
Tablespace created.
SQL&gt; create table testmyts (
 abc integer )
 tablespace myts;
Table created.
SQL&gt; </strong></pre>
<p>在oracle中，我们无需声明引擎类型，但要声明存储大小。我们可以创建一个小体积的存储空间，然后使用autoextend让其自动扩展，但是这个存储大小是必须要初始化的。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.71j.cn/archives/155/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>恢复mysql的root密码</title>
		<link>http://www.71j.cn/archives/73</link>
		<comments>http://www.71j.cn/archives/73#comments</comments>
		<pubDate>Tue, 08 Sep 2009 09:56:13 +0000</pubDate>
		<dc:creator>杜工</dc:creator>
				<category><![CDATA[感悟]]></category>
		<category><![CDATA[mysql]]></category>

		<guid isPermaLink="false">http://71j.cn/?p=73</guid>
		<description><![CDATA[如果给你一台服务器，mysql环境都配置好了，却不知道root密码，怎么办？难道要重新安装mysql? 呵呵，我还真干过这事，后来受前辈教化，得出下面的密码恢复方法，整个过程不超过2分钟。 首... ]]></description>
			<content:encoded><![CDATA[<p>如果给你一台服务器，mysql环境都配置好了，却不知道root密码，怎么办？难道要重新安装mysql? 呵呵，我还真干过这事，后来受前辈教化，得出下面的密码恢复方法，整个过程不超过2分钟。</p>
<p>首先向mysqld server 发送kill命令关掉mysqld server(不要用kill -9),存放进程ID的文件通常在MYSQL的数据库所在的目录/var/lib/mysql中，也可以用ps查看。</p>

<div class="wp_syntax"><div class="code"><pre class="perl" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># killall -TERM mysqld</span></pre></div></div>

<p>然后使用&#8211;skip-grant-tables参数来启动 mysqld。</p>

<div class="wp_syntax"><div class="code"><pre class="perl" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># /usr/bin/safe_mysqld --skip-grant-tables</span></pre></div></div>

<p>路径可以用locate找一下。</p>
<p>然后就可以无密码登录到mysqld server ，此时Mysql的密码和刚安装时一样，都是为空。现在我们可以使用mysqladmin来改变mysql的密码了。</p>

<div class="wp_syntax"><div class="code"><pre class="perl" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#mysqladmin -u root -p password newpassword</span></pre></div></div>

<p>最后记得要刷新权限表：</p>

<div class="wp_syntax"><div class="code"><pre class="perl" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># mysqladmin flush-privileges</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://www.71j.cn/archives/73/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>范式设计简单介绍(二)</title>
		<link>http://www.71j.cn/archives/66</link>
		<comments>http://www.71j.cn/archives/66#comments</comments>
		<pubDate>Tue, 08 Sep 2009 05:29:59 +0000</pubDate>
		<dc:creator>杜工</dc:creator>
				<category><![CDATA[分享]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[范式设计]]></category>

		<guid isPermaLink="false">http://71j.cn/?p=66</guid>
		<description><![CDATA[NF 理论在设计之初，主要是为了应付数据冗余与存储重复而出的。当越来越庞大的数据库应用出现时，高度设计的 NF 带来的好处与性能所带来的坏处相互抵消了。因为通常，越高层次的 NF 会划... ]]></description>
			<content:encoded><![CDATA[<h2>1.3]  Third Normal Form(3NF)</h2>
<p>3NF 要求所有的属性都直接依赖于 primary key。3NF 和 2NF 最大的不同之处是，2NF 有依赖传递性,而 3NF 不准许。</p>
<p> 例如,有一个符合 2NF 的表：</p>
<p>错误方式：</p>
<p>+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<p>..some属性s  | 用户号    | 用户发表文章数 | 用户登录数| 用户积分 |  other 列 &#8230;</p>
<p>+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>……           |  ID_001 |    4           |     20    |    13    |    ……</p>
<p>+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<p align="center">用户积分规则：用户发表文章数 x 2  + 用户登录数 /4</p>
<p>  在 3NF 中是不符合的。因为‘用户积分’是通过‘用户发表文章数’和‘用户登录数’，用公式计算得来的。也就是说，‘用户积分’依赖于‘用户发表文章数’和‘用户登录数’。</p>
<p>  3NF 符合的划分方式是：</p>
<p>正确方式：</p>
<p>+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>..some属性s  | 用户号    | 用户发表文章数 | 用户登录数|  other 列 &#8230;</p>
<p>+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>……           |  ID_001 |    4           |     20    |    ……</p>
<p>+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>正确方式：</p>
<p>+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>..some属性s  | 用户号    |  用户积分 |  other 列 &#8230;</p>
<p>+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>……           |  ID_001 |     13    |    ……</p>
<p>+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>用户积分规则不变</p>
<p> 需要注意的是，虽然 3NF 更加清楚地将用户资料和用户积分这两个关系表示了出来。但是在需要联合查询用户资料和积分的情况下，在大多数 RDBMS 如 MySQL 中，会造成性能消耗严重的情况。进一步讨论在 1.4 中进行。</p>
<p>              1.3.1]    Joining 关系</p>
<p> 关系之间相互关联的方式有两种：INNER　JOIN  和 OUTER JOIN</p>
<p>  INNER JOIN 查询会返回两个关系完全匹配的情况，MYSQL 默认的匹配方式为 INNER JOIN 。</p>
<p>  如果你希望查询的结果即使没有匹配也会被查询出来，那么就要使用 OUTER JOIN 的连接方式。OUTER JOIN 又细分为三种：LEFT OUTER JOIN, RIGHT OUTER JOIN 和 FULL OUTER JOIN 。</p>
<p>  LEFT　OUTER JOIN 是将左边的查询关系作为主关系，如果右面的关系有相匹配的 tuple , 那么处理方式和 INNER JOIN 一样；如果右面的关系没有与左边的关系相匹配，那么属性就会列出一个 NULL 的值。</p>
<p>  RIGHT OUTER JOIN 的处理方式与 LEFT OUTER JOIN 类似，只不过是以右面的关系为主 关系。</p>
<p>  FULL OUTER JOIN 与 INNER JOIN 的显示结果相同。</p>
<h3>            1.3.2]    BCNF</h3>
<p> 修正的第三范式(BCNF) 全称 Boyce-Codd normal form 。是 3NF 的一个拓展，所以 BCNF 的前提和 3NF 是一样的：关系 必须符合 2NF ，并且有 KEY 可以用来相互关联。并不是所有符合 2NF 的关系都可以划分为 BCNF。</p>
<p>  BCNF 简单来说，就是所有的 tuple 都依赖于 candidate key 或者这个 tuple 是 superkey 。因此所有的 tuple 都依赖于 key，从而避免了传递依赖问题。</p>
<h2>        1.4]  NF 设计与性能消耗</h2>
<p>NF 理论在设计之初，主要是为了应付数据冗余与存储重复而出的。当越来越庞大的数据库应用出现时，高度设计的 NF 带来的好处与性能所带来的坏处相互抵消了。因为通常，越高层次的 NF 会划分越多的 关系，从而查询出所需要的数据就需要更多的 join 操作。虽然 view 在一定程度上可以解决这个问题，但是视图本身也是一个不小的性能消耗。</p>
<p> 如果一个 MySQL 执行的多是 SQL-Transaction 的话，那么使用高层次的 NF 设计就显得尤为必要，因为书写 transaction 的 SQL 语言通常都不适于做复杂的过程处理，而高层次的 NF 设计可以在逻辑上更清楚的划分关系，从而较少的操作关系之间的关系处理，较多的操作关系之间的数据。</p>
<p> 而如果一个 MySQL 在应用中 ，更多的是扮演数据存储与统计的操作，那么高层次的 NF 设计就没有必要。因为此类应用中，通常都搭配使用高级编程语言，而高级编程语言灵活多样，在逻辑、过程与数据的处理过程中，都要比 SQL 更加的强壮。</p>
<h2>        1.5]  NF 与 SQL 的关系</h2>
<p>SQL 语言是为了结构化的查询数据而发明的一种机器查询语言。主要的功能是查询，兼顾数据定义与控制的功能。</p>
<p> SQL 大致可以分为三类：</p>
<h3>1.5.1]    Data Manipulation Language (DML)</h3>
<p>        DML 主要用来 查/删/改/插关系的 tuple 。他们共同的特点是都需要指定作用的关系和关系之间的关系。</p>
<p>        1.5.1.1]    Select</p>
<p>    Select 用来查询关系中的 tuple 包括:</p>
<p>        Select : 后面跟属性,作用是控制查询的输出。</p>
<p>        From : 后面跟关系与  joins ,作用是控制与关联关系之间的关系。</p>
<p>        Where : 后面跟属性的限制语句，主要是用来划分查询的区域。</p>
<p>        Group By : 后面跟属性,主要用来将相似的属性分成单一的结果集。</p>
<p>        Having : 与 Where 作用相同，作用域为 Group By 控制的结果集。</p>
<p>        Order By: 用来将最后筛选出来的结果集，通过某一 tuple 来进行排序。</p>
<p>    具体作用详见：1.2.1]</p>
<p>        1.5.1.2]    Insert</p>
<p>    Insert 用来插入 tuple。具体作用详见：1.2.2]</p>
<p>        1.5.1.3]    Update</p>
<p>    Update 用来更新 tuple 。具体作用详见：1.2.3]</p>
<p>        1.5.1.4]    Delete</p>
<p>    Delete 用来删除 tuple 。作用域与 Select 类似，但是不返回查询的 tuple。</p>
<h3>1.5.2]    Data Definition Language (DDL)</h3>
<p>        DDL 的作用是创建关系与定义关系中的属性。主要包括三大部分：</p>
<p>        1.5.2.1]  CREATE </p>
<p>    创建语句,可以用来创建 Database、关系、transaction(祥见 1.2.4) 等。根据需要创建的类型不同，语句稍有差别。</p>
<p>        1.5.2.2]  DROP</p>
<p>    删除语句，与 CREATE 语句相反。</p>
<p>        1.5.2.3]  ALTER</p>
<p>    修改关系和 Transaction 。</p>
<h3>1.5.3]    Data Control Language (DCL)</h3>
<p>        DCL 的作用是用来控制关系和属性的权限。主要有两部分：</p>
<p>        1.5.3.1]  GRANT</p>
<p>    用来创建访问关系与属性的权限</p>
<p>        1.5.3.2]  REVOKE</p>
<p>    用来删除访问关系与属性的权限</p>
<p>原文作者：韩述 杜工稍作修改。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.71j.cn/archives/66/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>范式设计简单介绍(一)</title>
		<link>http://www.71j.cn/archives/62</link>
		<comments>http://www.71j.cn/archives/62#comments</comments>
		<pubDate>Tue, 08 Sep 2009 05:27:03 +0000</pubDate>
		<dc:creator>杜工</dc:creator>
				<category><![CDATA[分享]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[范式设计]]></category>

		<guid isPermaLink="false">http://71j.cn/?p=62</guid>
		<description><![CDATA[ 范式设计是关系数据库的一个延伸理论。目的是在关系数据库的基础上，减少重叠数据的冗余，并且在将列(属性) 逐渐拆分成表(关系) 的过程中，从理论上减少了异常数据产生的几率。增强了... ]]></description>
			<content:encoded><![CDATA[<p>    范式设计是关系数据库的一个延伸理论。目的是在关系数据库的基础上，减少重叠数据的冗余，并且在将列(属性) 逐渐拆分成表(关系) 的过程中，从理论上减少了异常数据产生的几率。增强了数据的关系性能，在一定程度上，增强了关系查询效率。       </p>
<p>        术语：通常在具体的 RDBMS 如 MySQL 的应用开发中，将一个关系叫做表，一条元组（tuple） 称为行，一个属性叫做列。     因为范式（NF） 设计主要是讲理论，所以在本文中，一律将表称为关系，将行称为tuple，将列称为属性。</p>
<p>如图：</p>
<p><img class="aligncenter size-full wp-image-71" title="范式设计" src="http://71j.cn/wp-content/uploads/2009/09/范式设计.jpg" alt="范式设计" width="551" height="237" /></p>
<h2>        1.1]  First Normal Form(1NF)</h2>
<p>1NF(第一范式)  的目的是将数据拆分成原子状态。例如 一个大型文章发布系统的文章序列号的组成是 8 位用户名 + 该用户所属的文章号，如某用户的用户名是 ID_001 ，他发表的某一篇文章，在他的文章列表中的序列号是 15 ，这篇文章在该系统中唯一序列号是 ID_00115 。</p>
<p> 将文章序列号存储到关系中去，通常的做法是这样的：</p>
<p>错误的方式</p>
<p>+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;+</p>
<p>some属性……  |   文章序列号    | other 列……</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>……|   ID_00115    |</p>
<p>这么做是不符合 1NF 规范的。因为文章序列号是两部分组成的，如果存成一个属性那么就违反了 1NF 的原子性原则。</p>
<p> 符合 1NF 的属性划分方法如下：</p>
<p> 正确方式：</p>
<p>+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;+</p>
<p>some属性…… |  用户号  | 文章号 | other 列……</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>……| ID_001       |  15      |</p>
<p>+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;+</p>
<h2>        1.2]  Second Normal Form（2NF）</h2>
<p>2NF 划分关系的原则是：一个关系中的所有非 Key属性s 必须完全的依赖于 Key。如果是多主键的话，那么非主键属性s 必须完全依赖所有的主键.</p>
<p> 1NF 的范围是同一关系的不同属性之间的划分。而 2NF(第二范式) 的范围是将一个大的，数据相互重叠与冗余的关系拆分成众多小的，关系 ，他们之间相互的联系就是 Key ，Key 是一个关系中唯一标示一个tuple 的标识。而且在 2NF 中，所有有效的单一的 Key 默认都是 Primary key。(多个 Key 唯一定位一个tuple ,那么这些Key 称为复合主键) 。</p>
<p> 另外一点需要特别注意的是，范式是属性递增的，因此，只有在完成了 1NF 之后，才能进行 2NF 的划分。</p>
<p> 例如某文章系统中，一个存储某一篇文章的关系，有如下字段 </p>
<p>错误方式：</p>
<p> +&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<p>..some属性s       |  用户号    |  文章号  |  文章标题 |  文章内容 | 文章创建时间 | 用户发表文章数 | 用户登录数| other 列 &#8230;</p>
<p>+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<p>……|   ID_001 |   15     |  Article  | Cnt &#8230;   |  1223372589  |      4         |     20    |  ……</p>
<p> 其中，‘用户号’和‘文章号’对于 ‘文章标题’、‘文章内容’、‘文章创建时间’来说，可以算是复合主键，因为要查出这些属性，必须完全依赖 ‘文章号’和 ‘用户号’这两个属性，缺一不可。</p>
<p> 而 ‘用户发表文章数’和 ‘用户登录数’这两个属性仅依靠 ‘用户号’就可以出来，所以 ‘用户号’是 ‘用户发表文章数’和 ‘用户登录数’的主键，而 ‘文章号’则和这两个属性没有关系。也可以说 ‘用户发表文章数’和 ‘用户登录数’没有完全依赖于复合主键，所以这个表不符合 2NF 标准(但是所有属性都是原子不可分状态，因此这个表符合 1NF 标准)。</p>
<p> 如果要符合 2NF 标准，就需要将这个关系拆分成两个关系</p>
<p> 正确方式：</p>
<p>+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>..some属性s       |  用户号    |  文章号  |  文章标题 |  文章内容 | 文章创建时间 | other 列 &#8230;</p>
<p>+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>……|   ID_001 |   15     |  Article  | Cnt &#8230;   |  1223372589  |       ……</p>
<p>+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;  </p>
<p> 正确方式：</p>
<p>+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>..some属性s       |  用户号    |  用户发表文章数 | 用户登录数| other 列 &#8230;</p>
<p>+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>……|   ID_001 |     4           |     20    |  ……</p>
<p>+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-  </p>
<p> 这样，Right way one . 中剔出了不符合完全依赖的两个属性s ，所有的属性s 都完全依赖 composite primary key ，可以认为 Right way one. 符合 2NF 标准。</p>
<p>另外，将 Wrong way. 中剔出的两个属性s 划分到了 Right way two. 里面，primary key 是 ‘用户号’。因此 Right way two. 仅就一个 primary key ，并且所有内容都依赖于 primary key 查询，所以可以说 Right way two. 符合 2NF 的要求。</p>
<h3>            1.2.1]   关系模式</h3>
<p>经过 2NF 的拆分，现在关系的数量在增加，但是属性之间的关系趋向于更加的简单明了。 </p>
<p>关系之间根据对应联系的不同，有三种不同的关系模式：</p>
<p>    ·  一对一</p>
<p>    ·  一对多</p>
<p>    ·  多对多</p>
<p> ·一对一 ， 既一个属性仅可以对应一个其他的属性</p>
<p>    例如：一个用户号和用户之间就是一对一的关系，一个用户只能有一个用户号，一个用户号只能指定某一个用户。</p>
<p>·一对多 ， 既一个属性可以对应多个其他的属性</p>
<p>    例如: 一个用户号可以对应多个文章号,因为用户可以发表多篇的文章.</p>
<p>·多对多 ， 既多个属性可以对应多个其他的属性</p>
<p>    完全多对多就是 Cartesian product(笛卡尔积或直积)。</p>
<p>    例如: 一个用户可以发相同标题的不同文章。而拥有相同标题的文章，可以由不同的用户发。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.71j.cn/archives/62/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

