node.js之mysql npm包学习
<p><span style="font-family: 幼圆; font-size: 18px">做学校项目时需要用node.js去连接mysql数据库,于是打算将npm包中mysql的用法全部翻译下来,顺便整理笔记,原文传送门<br></span></p><p><span style="font-family: 幼圆; font-size: 18px">这是一个mysql的node.js驱动程序。他是用JS编写的,不需要编译,并且100%获得MIT许可。下面是一个如何使用它的例子</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> mysql = require(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">mysql</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">var</span> connection =<span style="color: rgba(0, 0, 0, 1)"> mysql.createConnection({
host : </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">localhost</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">,
user : </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">me</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">,
password : </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">secret</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">,
database : </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">my_db</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">
});
connection.connect();
connection.query(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">SELECT 1 + 1 AS solution</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, function (error, results, fields) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (error) <span style="color: rgba(0, 0, 255, 1)">throw</span><span style="color: rgba(0, 0, 0, 1)"> error;
console.log(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">The solution is: </span><span style="color: rgba(128, 0, 0, 1)">'</span>, results[<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">].solution);
});
connection.end();</span></pre>
</div>
<p><span style="font-family: 幼圆; font-size: 18px">从这个例子中,你可以学到以下内容:</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">1、你在连接上调用的每个方法都是按顺序排队执行的。</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">2、调用end()方法关闭连接,它确保所有剩余的查询在发送一个退出连接的包到mysql数据库前执行完成。</span></p>
<p> </p>
<p><strong><span style="font-family: 幼圆; font-size: 18pt">建立连接</span></strong></p>
<p><span style="font-family: 幼圆; font-size: 18pt"><span style="font-size: 18px">推荐用这个方法来建立连接:</span></span><strong><span style="font-family: 幼圆; font-size: 18pt"><br></span></strong></p>
<p> </p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> mysql = require(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">mysql</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">var</span> connection =<span style="color: rgba(0, 0, 0, 1)"> mysql.createConnection({
host : </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">example.org</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">,
user : </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">bob</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">,
password : </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">secret</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">
});
connection.connect(function(err) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (err) {
console.error(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">error connecting: </span><span style="color: rgba(128, 0, 0, 1)">'</span> +<span style="color: rgba(0, 0, 0, 1)"> err.stack);
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
}
console.log(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">connected as id </span><span style="color: rgba(128, 0, 0, 1)">'</span> +<span style="color: rgba(0, 0, 0, 1)"> connection.threadId);
});</span></pre>
</div>
<p> </p>
<p><span style="font-family: 幼圆; font-size: 18px">但是,一个连接也可以通过调用query方法被隐式建立:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> mysql = require(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">mysql</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">var</span> connection =<span style="color: rgba(0, 0, 0, 1)"> mysql.createConnection(...);
connection.query(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">SELECT 1</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, function (error, results, fields) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (error) <span style="color: rgba(0, 0, 255, 1)">throw</span><span style="color: rgba(0, 0, 0, 1)"> error;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> connected!</span>
});</pre>
</div>
<p><span style="font-family: 幼圆; font-size: 18px">这取决于你喜欢怎样处理你的errors,两种方法都可能是合适的。任何类型的连接错误(握手或网络)都被认为是致命错误,有关更多信息,请参阅错误处理部分。</span></p>
<p><strong><span style="font-family: 幼圆; font-size: 18pt">连接选项(只列出常用的)</span></strong></p>
<p><span style="font-size: 18px"><span style="font-family: 幼圆">当你建立一个连接的时候你可以设置以下选项:</span></span></p>
<p><span style="font-size: 18px"><span style="font-family: 幼圆">host:你连接数据库的主机名,默认是localhost;</span></span></p>
<p><span style="font-size: 18px"><span style="font-family: 幼圆">port:你连接的端口号,默认3306;</span></span></p>
<p><span style="font-size: 18px"><span style="font-family: 幼圆">localAddress:用于TCP连接的源IP地址</span></span></p>
<p><span style="font-size: 18px"><span style="font-family: 幼圆">user:mysql用户名;</span></span></p>
<p><span style="font-size: 18px"><span style="font-family: 幼圆">password:mysql用户对应的密码;</span></span></p>
<p><span style="font-size: 18px"><span style="font-family: 幼圆">database:连接的数据库名;</span></span></p>
<p><span style="font-size: 18px"><span style="font-family: 幼圆">charset:用于该连接的字符编码。默认是UTF8_GENERAL_CI</span></span></p>
<p><span style="font-size: 18px"><span style="font-family: 幼圆">timezone:mysql服务器上设置的时区。它用于将服务器日期/时间值转换为js日期对象,反之亦然。可以是"local","z",或者+HH:MM或-HH:MM格式的偏移量。(默认值是“本地”)</span></span></p>
<p><span style="font-size: 18px"><span style="font-family: 幼圆">connectTimeout:在初始连接MySQL服务器时超时前的毫秒数。(默认:10000)</span></span></p>
<p><span style="font-size: 18px"><span style="font-family: 幼圆">datestring:强制日期类型(TIMESTAMP, DATETIME, date)作为字符串返回,而不是膨胀成JavaScript日期对象。可以是true/false,也可以是作为字符串保存的类型名数组。(默认值:false)</span></span></p>
<p><span style="font-size: 18px"><span style="font-family: 幼圆">debug:打印协议细节到stdout。可以为true/false或应该打印的数据包类型名称数组。(默认值:false)</span></span></p>
<p><span style="font-size: 18px"><span style="font-family: 幼圆">trace:在出错时生成堆栈跟踪,包括图书馆入口的调用位置(“长堆栈跟踪”)。大多数调用的性能损失较小。(默认值是true)</span></span></p>
<p><span style="font-size: 18px"><span style="font-family: 幼圆"><code>multipleStatements</code>:允许每个查询使用多个mysql语句。注意,这可能会增加SQL注入攻击的范围。(默认值:false)</span></span></p>
<p><span style="font-size: 18px"><span style="font-family: 幼圆">flag<strong>:</strong></span></span><span style="font-size: 18px; font-family: 幼圆">要使用的连接标志的列表(默认连接标志除外)。也可以将默认的黑名单。有关更多信息,请检查连接标志。</span></p>
<p> </p>
<p> </p>
<p> </p>
<p><span style="font-size: 18px"><span style="font-family: 幼圆">除了传递选项对象,你还可以使用url字符串。例如:</span></span></p>
<p><span style="font-size: 18px"><span style="font-family: 幼圆"><span class="storage type js">var connection <span class="keyword operator assignment js">= <span class="variable other object js">mysql<span class="meta js"><span class="meta delimiter method period js">.<span class="entity name function js">createConnection<span class="meta js"><span class="punctuation definition begin round js">(<span class="string quoted single js"><span class="punctuation definition string begin js">'mysql://user:pass@host/db?debug=true&charset=BIG5_CHINESE_CI&timezone=-0700<span class="punctuation definition string end js">'<span class="punctuation definition end round js">)<span class="punctuation terminator statement js">;</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></p>
<p><span style="font-size: 18px"><span style="font-family: 幼圆"><span class="storage type js"><span class="keyword operator assignment js"><span class="variable other object js"><span class="meta js"><span class="meta delimiter method period js"><span class="entity name function js"><span class="meta js"><span class="punctuation definition begin round js"><span class="string quoted single js"><span class="punctuation definition string begin js"><span class="punctuation definition string end js"><span class="punctuation definition end round js"><span class="punctuation terminator statement js">这个查询值首先尝试被解析成json对象,如果失败了则转换为文本字符串。</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></p>
<p> </p>
<p><span style="font-size: 18pt"><strong><span style="font-family: 幼圆"><span class="storage type js"><span class="keyword operator assignment js"><span class="variable other object js"><span class="meta js"><span class="meta delimiter method period js"><span class="entity name function js"><span class="meta js"><span class="punctuation definition begin round js"><span class="string quoted single js"><span class="punctuation definition string begin js"><span class="punctuation definition string end js"><span class="punctuation definition end round js"><span class="punctuation terminator statement js">连接标志</span></span></span></span></span></span></span></span></span></span></span></span></span></span></strong></span></p>
<p><span style="font-family: 幼圆; font-size: 18px"><span style="font-family: 幼圆">由于各种原因,你想要改变默认的连接标志,你可以使用连接选项flags。传递一个以逗号分隔的项目列表字符串,以添加到默认标志。如果你不想使用默认标志,在标志前加上一个负号。要添加不在默认列表中的标志,只需写入标志名,或在其前面加一个加号(不区分大小写)。</span></span></p>
<p> </p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> connection =<span style="color: rgba(0, 0, 0, 1)"> mysql.createConnection({
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> disable FOUND_ROWS flag, enable IGNORE_SPACE flag</span>
flags: <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">-FOUND_ROWS,IGNORE_SPACE</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">
});</span></pre>
</div>
<p> </p>
<p><span style="font-family: 幼圆; font-size: 18px">可用的标志自行查看官网~(你好懒)</span></p>
<p> </p>
<p><strong><span style="font-family: 幼圆; font-size: 18pt">终止连接</span></strong></p>
<p><span style="font-size: 18px"><span style="font-family: 幼圆">一共有两种方式终止连接。调用end()方法可以简洁地终止一个连接。</span></span></p>
<p> </p>
<div class="cnblogs_code">
<pre>connection.end(<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(err) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> The connection is terminated now</span>
});</pre>
</div>
<p> </p>
<p><span style="font-family: 幼圆; font-size: 18px">这将确保所有前面已经入队地查询仍然在发送一个COM_QUIT包到mysql数据库之前。如果在发送COM_QUIT包之前发生了一个致命的错误(如握手失败或者网络拥堵等),一个err参数将会提供给回调函数。无论如何,连接都会终止。</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">另一个可选的方法是调用destroy()方法。这会导致socket连接立刻终止。另外destory()方法保证不会产生其他事件和回调会被触发。</span></p>
<div class="cnblogs_code">
<pre>connection.destroy();</pre>
</div>
<p><span style="font-family: 幼圆; font-size: 18px">不像end()方法,destroy()方法没有回调参数。</span></p>
<p><strong><span style="font-family: 幼圆; font-size: 18pt">连接池</span></strong></p>
<p><span style="font-size: 18px"><span style="font-family: 幼圆">与一个一个创建和管理连接不同,该模块还使用mysql.createPool(config)提供了内置的连接池。</span></span></p>
<p><span style="font-family: 幼圆"><span style="font-size: 18px">创建一个连接池并且直接使用它:</span></span></p>
<p> </p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> mysql = require('mysql'<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">var</span> pool=<span style="color: rgba(0, 0, 0, 1)"> mysql.createPool({
connectionLimit : </span>10<span style="color: rgba(0, 0, 0, 1)">,
host : </span>'example.org'<span style="color: rgba(0, 0, 0, 1)">,
user : </span>'bob'<span style="color: rgba(0, 0, 0, 1)">,
password : </span>'secret'<span style="color: rgba(0, 0, 0, 1)">,
database : </span>'my_db'<span style="color: rgba(0, 0, 0, 1)">
});
pool.query(</span>'SELECT 1 + 1 AS solution', <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> (error, results, fields) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (error) <span style="color: rgba(0, 0, 255, 1)">throw</span><span style="color: rgba(0, 0, 0, 1)"> error;
console.log(</span>'The solution is: ', results.solution);
});</span></pre>
</div>
<p> </p>
<p><span style="font-family: 幼圆; font-size: 18px">这是pool.getConnection() -> connection.query() -> connection.release()代码流的快捷方式。使用pool.getConnection()可以为后续查询共享连接状态。这是因为对pool.query()的两次调用可能会使用两个不同的连接并并行运行。这是基本结构:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> mysql = require('mysql'<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">var</span> pool=<span style="color: rgba(0, 0, 0, 1)"> mysql.createPool(...);
pool.getConnection(</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(err, connection) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (err) <span style="color: rgba(0, 0, 255, 1)">throw</span> err; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> not connected!</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Use the connection</span>
connection.query('SELECT something FROM sometable', <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> (error, results, fields) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> When done with the connection, release it.</span>
<span style="color: rgba(0, 0, 0, 1)"> connection.release();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Handle error after the release.</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> (error) <span style="color: rgba(0, 0, 255, 1)">throw</span><span style="color: rgba(0, 0, 0, 1)"> error;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Don't use the connection here, it has been returned to the pool.</span>
<span style="color: rgba(0, 0, 0, 1)">});
});</span></pre>
</div>
<p><span style="font-family: 幼圆; font-size: 18px">如果你想要关闭连接并且将它从连接池中移出去,使用connection.destory()代替release()。</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">池将在下次需要连接时创建一个新连接。</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">连接是由池惰性创建的。如果您将连接池配置为允许最多100个连接,但只同时使用5个连接,那么只会建立5个连接。连接也是循环循环的,连接从池的顶部获取,然后返回到池的底部。</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">当从池中检索到先前的连接时,一个ping包被发送到服务器,以检查连接是否仍然有效。</span></p>
<p><strong><span style="font-family: 幼圆; font-size: 18pt">连接池选项</span></strong></p>
<p><span style="font-size: 18px"><span style="font-family: 幼圆">连接池可以一个连接都是相同的选项。当创建一个新连接时,选项直接作为连接构造函数的参数。另外连接池接受几个额外的选项:</span></span></p>
<p><span style="font-size: 18px"><span style="font-family: 幼圆">1、acquireTimeout</span></span></p>
<p><span style="font-size: 18px"><span style="font-family: 幼圆">在连接获取过程中发生超时之前的毫秒数。这与connectTimeout稍有不同,因为获取池连接并不总是涉及建立连接。如果连接请求进入队列,则请求在队列中花费的时间不计入此超时。(默认:10000)</span></span></p>
<p><span style="font-size: 18px"><span style="font-family: 幼圆">2、waitForConnection</span></span></p>
<p><span style="font-size: 18px"><span style="font-family: 幼圆">确定当没有连接可用且已达到限制时池的操作。如果为true,则池将对连接请求进行排队,并在连接请求可用时调用它。如果为false,池将立即回调一个错误。(默认值是真实的)</span></span></p>
<p><span style="font-size: 18px"><span style="font-family: 幼圆">3、connectionLimit:一次连接的最大数量(默认是10);</span></span></p>
<p><span style="font-size: 18px"><span style="font-family: 幼圆">4、queueLimit:queueLimit:在从getConnection返回错误之前,连接池将排队的最大连接请求数。如果设置为0,则对排队的连接请求数没有限制。(默认值:0);</span></span></p>
<p><strong><span style="font-size: 18pt"><span style="font-family: 幼圆">连接池事件</span></span></strong></p>
<p><span style="font-size: 18px"><strong>acquire</strong></span></p>
<p><span style="font-size: 18px; font-family: 幼圆">当从池中获取连接时,池将发出一个acquire事件。在连接上执行了所有的获取活动之后,也就是将连接交给获取代码的回调之前,调用这个函数。</span></p>
<div class="cnblogs_code">
<pre>pool.on('acquire', <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> (connection) {
console.log(</span>'Connection %d acquired'<span style="color: rgba(0, 0, 0, 1)">, connection.threadId);
});</span></pre>
</div>
<p> </p>
<p><strong><span style="font-size: 18px; font-family: 幼圆">connection</span></strong></p>
<p> </p>
<p><span style="font-size: 18px; font-family: 幼圆">当在池中建立新连接时,池将发出连接事件。如果在使用连接之前需要在连接上设置会话变量,则可以侦听连接事件。</span></p>
<div class="cnblogs_code">
<pre>pool.on('connection', <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> (connection) {
connection.query(</span>'SET SESSION auto_increment_increment=1'<span style="color: rgba(0, 0, 0, 1)">)
});</span></pre>
</div>
<p><strong><span style="font-family: 幼圆; font-size: 18px">enqueue</span></strong></p>
<p> </p>
<p><span style="font-family: 幼圆; font-size: 18px">当回调函数排队等待可用连接时,池将发出排队事件。</span></p>
<div class="cnblogs_code">
<pre>pool.on('enqueue', <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> () {
console.log(</span>'Waiting for available connection slot'<span style="color: rgba(0, 0, 0, 1)">);
});</span></pre>
</div>
<p> </p>
<p> </p>
<p> </p>
<p><strong><span style="font-family: 幼圆; font-size: 18px">release</span></strong></p>
<p><span style="font-family: 幼圆; font-size: 18px">当一个连接被释放回连接池时,连接池会触发release事件。在所有释放活动执行完后调用它,所以在该事件发生时,连接处于空闲状态。</span></p>
<p> </p>
<div class="cnblogs_code">
<pre>pool.on('release', <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> (connection) {
console.log(</span>'Connection %d released'<span style="color: rgba(0, 0, 0, 1)">, connection.threadId);
});</span></pre>
</div>
<p> </p>
<p> </p>
<p><span style="font-size: 18pt; font-family: 幼圆"><strong>关掉连接池中的所有连接</strong></span></p>
<p><span style="font-size: 18px; font-family: 幼圆">当你使用完一个连接池后,你不得不关闭它的所有连接否则node.js的事件循环会保持活跃直到连接被mysql关闭服务。如果在脚本中使用池,或者试图优雅地关闭服务器,通常会这样做。要结束池中的所有连接,请使用池中的end方法:</span></p>
<div class="cnblogs_code">
<pre>pool.end(<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> (err) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> all connections in the pool have ended</span>
});</pre>
</div>
<p><span style="font-family: 幼圆; font-size: 18px">end方法右一个可选的回调函数使你可以知道所有的连接关闭了;</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">一旦end方法被调用,pool.getConnection方法和其他方法就不会再执行。所以在调用end方法之前要等待池中的连接释放。如果你用了pool.query的快捷方法,也等待它完成再调用end方法。</span></p>
<p><span style="font-family: 幼圆"><span style="font-size: 18px">pool的end方法会调用连接池中所有的connection的end方法,这将使quit包在连接中排队并设置一个标志来防止连接池建立新的连接。所有正在执行的命令都将完成,但是新的命令将不会执行。</span></span></p>
<p> </p>
<p><strong><span style="font-family: 幼圆; font-size: 18pt">连接池集群</span></strong></p>
<p><span style="font-size: 18px"><span style="font-family: 幼圆">连接池集群提供多个主机的连接:</span></span></p>
<p> </p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> create</span>
<span style="color: rgba(0, 0, 255, 1)">var</span> poolCluster =<span style="color: rgba(0, 0, 0, 1)"> mysql.createPoolCluster();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> add configurations (the config is a pool config object)</span>
poolCluster.add(config); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> add configuration with automatic name</span>
poolCluster.add(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">MASTER</span><span style="color: rgba(128, 0, 0, 1)">'</span>, masterConfig); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> add a named configuration</span>
poolCluster.add(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">SLAVE1</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, slave1Config);
poolCluster.add(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">SLAVE2</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, slave2Config);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> remove configurations</span>
poolCluster.remove(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">SLAVE2</span><span style="color: rgba(128, 0, 0, 1)">'</span>); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> By nodeId</span>
poolCluster.remove(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">SLAVE*</span><span style="color: rgba(128, 0, 0, 1)">'</span>); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> By target group : SLAVE1-2
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Target Group : ALL(anonymous, MASTER, SLAVE1-2), Selector : round-robin(default)</span>
<span style="color: rgba(0, 0, 0, 1)">poolCluster.getConnection(function (err, connection) {});
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Target Group : MASTER, Selector : round-robin</span>
poolCluster.getConnection(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">MASTER</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, function (err, connection) {});
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Target Group : SLAVE1-2, Selector : order
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> If can't connect to SLAVE1, return SLAVE2. (remove SLAVE1 in the cluster)</span>
poolCluster.on(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">remove</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, function (nodeId) {
console.log(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">REMOVED NODE : </span><span style="color: rgba(128, 0, 0, 1)">'</span> + nodeId); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> nodeId = SLAVE1</span>
<span style="color: rgba(0, 0, 0, 1)">});
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> A pattern can be passed with *as wildcard</span>
poolCluster.getConnection(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">SLAVE*</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">ORDER</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, function (err, connection) {});
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> The pattern can also be a regular expression</span>
poolCluster.getConnection(/^SLAVE[<span style="color: rgba(128, 0, 128, 1)">12</span>]$/<span style="color: rgba(0, 0, 0, 1)">, function (err, connection) {});
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> of namespace : of(pattern, selector)</span>
poolCluster.of(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">*</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">).getConnection(function (err, connection) {});
</span><span style="color: rgba(0, 0, 255, 1)">var</span> pool = poolCluster.of(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">SLAVE*</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">RANDOM</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">);
pool.getConnection(function (err, connection) {});
pool.getConnection(function (err, connection) {});
pool.query(function (error, results, fields) {});
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> close all connections</span>
<span style="color: rgba(0, 0, 0, 1)">poolCluster.end(function (err) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> all connections in the pool cluster have ended</span>
});</pre>
</div>
<p> </p>
<p><strong><span style="font-family: 幼圆; font-size: 18px">连接池集群选项</span></strong></p>
<p><span style="font-family: 幼圆; font-size: 18px">canRetry:如果为true,当连接失败时,连接池集群会尝试重连。默认为真。</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">removeNodeErrorCount:如果连接失败,节点的errorCount会增长。当errorCount大于removeNodeErrorCount,将从连接池集群中移走一个节点。</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">restoreNodeTimeout:如果连接失败,指定再次尝试连接的毫秒数。如果设置为0,则node将被删除,并且永远不会被重用。(默认值:0)</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">defaultSelector:</span><span style="font-family: 幼圆; font-size: 18px">默认的选择器。(默认值:RR)</span></p>
<p> </p>
<p><span style="font-family: 幼圆; font-size: 18px">RR:交替选择。(循环)</span></p>
<p> </p>
<p><span style="font-family: 幼圆; font-size: 18px">RANDOM:按随机函数选择节点。</span></p>
<p> </p>
<p><span style="font-family: 幼圆; font-size: 18px">ORDER:无条件地选择第一个可用的节点。</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> clusterConfig =<span style="color: rgba(0, 0, 0, 1)"> {
removeNodeErrorCount: </span><span style="color: rgba(128, 0, 128, 1)">1</span>, <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Remove the node immediately when connection fails.</span>
defaultSelector: <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">ORDER</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">
};
</span><span style="color: rgba(0, 0, 255, 1)">var</span> poolCluster = mysql.createPoolCluster(clusterConfig);</pre>
</div>
<p> </p>
<p><strong><span style="font-family: 幼圆; font-size: 18pt">切换用户和修改连接状态</span></strong></p>
<p><span style="font-size: 18px"><span style="font-family: 幼圆">mysql提供一个切换用户的命令来允许你改变当前用户和其他方面的连接,而不关闭底层套接字:</span></span></p>
<p> </p>
<div class="cnblogs_code">
<pre>connection.changeUser({user : <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">john</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">}, function(err) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (err) <span style="color: rgba(0, 0, 255, 1)">throw</span><span style="color: rgba(0, 0, 0, 1)"> err;
});</span></pre>
</div>
<p> </p>
<p><span style="font-family: 幼圆; font-size: 18px">对于这个特征可获得的选项有:</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">user:你要切换的用户名,默认是原用户名。</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">password:切换的用户密码,默认是原密码。</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">charset:新的字符编码,默认是原字符编码;</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">database:新的数据库,默认是原数据库。</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">这个功能的一个副作用是,这个函数还会重置任何连接状态(变量、事务等)。</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">在此操作过程中遇到的错误将被此模块视为致命连接错误。</span></p>
<p><strong><span style="font-family: 幼圆; font-size: 18pt">服务器连接失败</span></strong></p>
<p><span style="font-size: 18px"><span style="font-family: 幼圆">你可能由于网络原因没能成功连上mysql服务器</span></span></p>
<p> </p>
<p><span style="font-family: 幼圆; font-size: 18px">服务器超时,服务器重新启动,或者崩溃。所有这些事件都被认为是致命错误,并且会出现err。代码=“PROTOCOL_CONNECTION_LOST”。有关更多信息,请参阅错误处理部分。</span></p>
<p> </p>
<p><span style="font-family: 幼圆; font-size: 18px">重新连接连接是通过建立一个新的连接来完成的。一旦终止,现有的连接对象就不能通过设计重新连接。</span></p>
<p> </p>
<p><span style="font-family: 幼圆; font-size: 18px">使用池,断开连接的连接将从池中删除,从而释放空间,以便在下一个getConnection调用中创建新的连接。</span></p>
<p> </p>
<p><span style="font-family: 幼圆; font-size: 18px">使用PoolCluster,断开的连接将算作相关节点的错误,并增加该节点的错误代码。一旦给定节点上的错误超过removeNodeErrorCount,则将其从集群中删除。发生这种情况时,如果模式不再有任何匹配的节点,PoolCluster可能会发出POOL_NONEONLINE错误。restoreNodeTimeout配置可以设置为在给定超时后恢复离线节点。</span></p>
<p> </p>
<p><span style="font-family: 幼圆; font-size: 18px"><strong><span style="font-size: 18pt">执行查询</span></strong></span></p>
<p><span style="font-family: 幼圆; font-size: 18px">最基础的执行查询方式是调用一个对象上的query()方法(像connnection,pool或者poolNamespace)。</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">query()方法最简便的形式是.query(sqlString,callback):</span></p>
<div class="cnblogs_code">
<pre>connection.query(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">SELECT * FROM `books` WHERE `author` = "David"</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, function (error, results, fields) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> error will be an Error if one occurred during the query
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> results will contain the results of the query
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> fields will contain information about the returned results fields (if any)</span>
});</pre>
</div>
<p><span style="font-family: 幼圆; font-size: 18px">第二种形式是.query(sqlString,values,callback),即使用占位符时可以用这个:</span></p>
<div class="cnblogs_code">
<pre>connection.query('SELECT * FROM `books` WHERE `author` = ?', ['David'], <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> (error, results, fields) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> error will be an Error if one occurred during the query</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> results will contain the results of the query</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> fields will contain information about the returned results fields (if any)</span>
});</pre>
</div>
<p><span style="font-family: 幼圆; font-size: 18px">第三种形式.query(选项,回调)是在对查询使用各种高级选项时出现的,比如转义查询值、连接重叠列名、超时和类型转换:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">connection.query({
sql: </span>'SELECT * FROM `books` WHERE `author` = ?'<span style="color: rgba(0, 0, 0, 1)">,
timeout: </span>40000, <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 40s</span>
values: ['David'<span style="color: rgba(0, 0, 0, 1)">]
}, </span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> (error, results, fields) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> error will be an Error if one occurred during the query</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> results will contain the results of the query</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> fields will contain information about the returned results fields (if any)</span>
});</pre>
</div>
<p><span style="font-family: 幼圆; font-size: 18px">请注意,在将占位符值作为参数传递而不是在options对象中传递时,可以使用第二和第三种形式的组合。values参数将覆盖option对象中的值:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">connection.query({
sql: </span>'SELECT * FROM `books` WHERE `author` = ?'<span style="color: rgba(0, 0, 0, 1)">,
timeout: </span>40000, <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 40s</span>
<span style="color: rgba(0, 0, 0, 1)">},
[</span>'David'<span style="color: rgba(0, 0, 0, 1)">],
</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> (error, results, fields) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> error will be an Error if one occurred during the query</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> results will contain the results of the query</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> fields will contain information about the returned results fields (if any)</span>
<span style="color: rgba(0, 0, 0, 1)">}
);</span></pre>
</div>
<p><span style="font-family: 幼圆; font-size: 18px">如果查询只有一个替换字符(?),且该值不是null、未定义或数组,它可以直接作为第二个参数传递给.query:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">connection.query(
</span>'SELECT * FROM `books` WHERE `author` = ?'<span style="color: rgba(0, 0, 0, 1)">,
</span>'David'<span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> (error, results, fields) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> error will be an Error if one occurred during the query</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> results will contain the results of the query</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> fields will contain information about the returned results fields (if any)</span>
<span style="color: rgba(0, 0, 0, 1)">}
);</span></pre>
</div>
<p> </p>
<p><strong><span style="font-family: 幼圆; font-size: 18pt">转义查询值</span></strong></p>
<p> </p>
<p><span style="font-family: 幼圆; font-size: 18px">注意这些转义值的方法只在禁用NO_BACKSLASH_ESCAPES SQL模式(这是MySQL服务器的默认状态)时有效。</span></p>
<p> </p>
<p><span style="font-family: 幼圆; font-size: 18px">为了避免SQL注入攻击,在SQL查询中使用数据之前,您应该始终对用户提供的数据进行转义。你可以使用mysql.escape(), connection.escape()或pool.escape()方法来实现:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> userId = <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">some user provided value</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">var</span> sql = <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">SELECT * FROM users WHERE id = </span><span style="color: rgba(128, 0, 0, 1)">'</span> +<span style="color: rgba(0, 0, 0, 1)"> connection.escape(userId);
connection.query(sql, function (error, results, fields) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (error) <span style="color: rgba(0, 0, 255, 1)">throw</span><span style="color: rgba(0, 0, 0, 1)"> error;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ...</span>
});</pre>
</div>
<p><span style="font-family: 幼圆; font-size: 18px">或者,你可以使用?字符来作为值的占位符,你可以这样转义:</span></p>
<div class="cnblogs_code">
<pre>connection.query(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">SELECT * FROM users WHERE id = ?</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, , function (error, results, fields) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (error) <span style="color: rgba(0, 0, 255, 1)">throw</span><span style="color: rgba(0, 0, 0, 1)"> error;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ...</span>
});</pre>
</div>
<p><span style="font-family: 幼圆; font-size: 18px">多个占位符按照传递的顺序映射到值。例如,在下面的查询中foo等于a, bar等于b, baz等于c, id将是userId:</span></p>
<div class="cnblogs_code">
<pre>connection.query(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">UPDATE users SET foo = ?, bar = ?, baz = ? WHERE id = ?</span><span style="color: rgba(128, 0, 0, 1)">'</span>, [<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">a</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">b</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">c</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, userId], function (error, results, fields) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (error) <span style="color: rgba(0, 0, 255, 1)">throw</span><span style="color: rgba(0, 0, 0, 1)"> error;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ...</span>
});</pre>
</div>
<p><span style="font-family: 幼圆; font-size: 18px">这看起来与MySQL中的预准备语句类似,但它实际上只是在内部使用了相同的connection.escape()方法。</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">不同的值类型有不同的转义方式,如下所示:</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">数字保持不变</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">布尔值被转换为真/假</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">Date对象被转换为'YYYY-mm-dd HH:ii:ss'字符串</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">缓冲区被转换为十六进制字符串,例如X'0fa5'</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">字符串是安全转义的</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">数组被转换为列表,例如['a', 'b']被转换为'a', 'b'</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">嵌套数组被转换成分组列表(用于批量插入),例如[['a', 'b'], ['c', 'd']]变成('a', 'b'), ('c', 'd')</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">具有toSqlString方法的对象将被调用.toSqlString(),并将返回值用作原始SQL。</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">对象被转换为对象上每个可枚举属性的key = 'val'对。如果属性的值是一个函数,则跳过它;如果属性的值是一个对象,则对其调用toString()并使用返回值。</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">undefined / null被转换为null</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">NaN / Infinity保持原样。MySQL不支持这些,并且尝试将它们作为值插入会触发MySQL错误,直到它们实现支持为止。</span></p>
<p> </p>
<p><span style="font-family: 幼圆; font-size: 18px">转义允许你做如下简洁的事情:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> post= {id: <span style="color: rgba(128, 0, 128, 1)">1</span>, title: <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Hello MySQL</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">};
</span><span style="color: rgba(0, 0, 255, 1)">var</span> query = connection.query(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">INSERT INTO posts SET ?</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, post, function (error, results, fields) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (error) <span style="color: rgba(0, 0, 255, 1)">throw</span><span style="color: rgba(0, 0, 0, 1)"> error;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Neat!</span>
<span style="color: rgba(0, 0, 0, 1)">});
console.log(query.sql); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> INSERT INTO posts SET `id` = 1, `title` = 'Hello MySQL'</span></pre>
</div>
<p><span style="font-family: 幼圆; font-size: 18px">并且toSqlString方法允许你用函数做如下复杂的查询:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> CURRENT_TIMESTAMP = { toSqlString: function() { <span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">CURRENT_TIMESTAMP()</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">; } };
</span><span style="color: rgba(0, 0, 255, 1)">var</span> sql = mysql.format(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">UPDATE posts SET modified = ? WHERE id = ?</span><span style="color: rgba(128, 0, 0, 1)">'</span>, );
console.log(sql); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> UPDATE posts SET modified = CURRENT_TIMESTAMP() WHERE id = 42</span></pre>
</div>
<p><span style="font-family: 幼圆; font-size: 18px">要使用toSqlString方法生成对象,可以使用mysql.raw()方法。这将创建一个对象,当使用在?占位符,用于将函数作为动态值使用:</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">注意提供给mysql.raw()的字符串在使用时将跳过所有转义函数,所以在传入未经验证的输入时要小心。</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> CURRENT_TIMESTAMP = mysql.raw(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">CURRENT_TIMESTAMP()</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">var</span> sql = mysql.format(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">UPDATE posts SET modified = ? WHERE id = ?</span><span style="color: rgba(128, 0, 0, 1)">'</span>, );
console.log(sql); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> UPDATE posts SET modified = CURRENT_TIMESTAMP() WHERE id = 42</span></pre>
</div>
<p><span style="font-family: 幼圆; font-size: 18px">如果你需要靠自己转义查询,你可以直接使用escaping 函数:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> query = <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">SELECT * FROM posts WHERE title=</span><span style="color: rgba(128, 0, 0, 1)">"</span> + mysql.escape(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Hello MySQL</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
console.log(query); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> SELECT * FROM posts WHERE title='Hello MySQL'</span></pre>
</div>
<p> </p>
<p><strong><span style="font-family: 幼圆; font-size: 18pt">转义查询标识符</span></strong></p>
<p><strong><span style="font-family: 幼圆; font-size: 18pt"><br></span></strong><span style="font-family: 幼圆; font-size: 18px">如果你不相信一个由用户提供的sql标识(数据库名,表明,列名),你应该用像这样使用<code>mysql.escapeId(identifier)</code>, <code>connection.escapeId(identifier)</code> or <code>pool.escapeId(identifier)</code> :</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> sorter = <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">date</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">var</span> sql = <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">SELECT * FROM posts ORDER BY </span><span style="color: rgba(128, 0, 0, 1)">'</span> +<span style="color: rgba(0, 0, 0, 1)"> connection.escapeId(sorter);
connection.query(sql, function (error, results, fields) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (error) <span style="color: rgba(0, 0, 255, 1)">throw</span><span style="color: rgba(0, 0, 0, 1)"> error;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ...</span>
});</pre>
</div>
<p> </p>
<p><span style="font-family: 幼圆; font-size: 18px">它还支持添加限定标识符。两部分都能转义:</span></p>
<p> </p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> sorter = <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">date</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">var</span> sql = <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">SELECT * FROM posts ORDER BY </span><span style="color: rgba(128, 0, 0, 1)">'</span> + connection.escapeId(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">posts.</span><span style="color: rgba(128, 0, 0, 1)">'</span> +<span style="color: rgba(0, 0, 0, 1)"> sorter);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> -> SELECT * FROM posts ORDER BY `posts`.`date`</span></pre>
</div>
<p> </p>
<p><span style="font-family: 幼圆; font-size: 18px">如果你不想将point作为限定标识符,你可以将第二个参数设置为true,以保持字符串作为文字标识符:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> sorter = <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">date.2</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">var</span> sql = <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">SELECT * FROM posts ORDER BY </span><span style="color: rgba(128, 0, 0, 1)">'</span> + connection.escapeId(sorter, <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> -> SELECT * FROM posts ORDER BY `date.2`</span></pre>
</div>
<p><span style="font-family: 幼圆; font-size: 18px">或者,你可以使用??作为标识的占位符,以便你可以这样转义:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> userId = <span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">var</span> columns = [<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">username</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">email</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">];
</span><span style="color: rgba(0, 0, 255, 1)">var</span> query = connection.query(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">SELECT ?? FROM ?? WHERE id = ?</span><span style="color: rgba(128, 0, 0, 1)">'</span>, , function (error, results, fields) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (error) <span style="color: rgba(0, 0, 255, 1)">throw</span><span style="color: rgba(0, 0, 0, 1)"> error;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ...</span>
<span style="color: rgba(0, 0, 0, 1)">});
console.log(query.sql); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> SELECT `username`, `email` FROM `users` WHERE id = 1</span></pre>
</div>
<p><span style="font-family: 幼圆; font-size: 18px">请注意,最后一个字符序列是实验性的,语法可能会改变</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">当您将对象传递给.escape()或.query()时,. escapeid()用于避免对象键中的SQL注入。</span></p>
<p> </p>
<p><span style="font-size: 18px"><strong><span style="font-family: 幼圆">准备查询</span></strong></span></p>
<p> </p>
<p><span style="font-family: 幼圆; font-size: 18px">你可以使用mysql.format()方法来准备一个具有多个插入点的查询,适当的利用转义来转义标识和值,如下一个简单例子:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> sql = <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">SELECT * FROM ?? WHERE ?? = ?</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">var</span> inserts = [<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">users</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">id</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, userId];
sql </span>= mysql.format(sql, inserts);</pre>
</div>
<p><span style="font-family: 幼圆; font-size: 18px">在此之后,您将获得一个有效的、转义的查询,然后可以安全地将该查询发送到数据库。如果您希望在实际将查询发送到数据库之前准备好查询,那么这是非常有用的。由于mysql.format()是通过SqlString.format()公开的,所以您还可以(但不是必需的)传入stringifyObject和timezone,这允许您提供将对象转换为字符串的自定义方法,以及特定于位置/时区的日期。</span></p>
<p><strong><span style="font-family: 幼圆; font-size: 18px">自定义格式</span></strong></p>
<p><span style="font-family: 幼圆; font-size: 18px">如果希望使用另一种类型的查询转义格式,可以使用连接配置选项定义自定义格式函数。如果想使用内置的.escape()或任何其他连接函数,可以访问连接对象。</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">下面是如何实现另一种格式的例子:</span></p>
<p> </p>
<div class="cnblogs_code">
<pre>connection.config.queryFormat =<span style="color: rgba(0, 0, 0, 1)"> function (query, values) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (!values) <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> query;
</span><span style="color: rgba(0, 0, 255, 1)">return</span> query.replace(/\:(\w+)/<span style="color: rgba(0, 0, 0, 1)">g, function (txt, key) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (values.hasOwnProperty(key)) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.escape(values);
}
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> txt;
}.bind(</span><span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">));
};
connection.query(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">UPDATE posts SET title = :title</span><span style="color: rgba(128, 0, 0, 1)">"</span>, { title: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Hello MySQL</span><span style="color: rgba(128, 0, 0, 1)">"</span> });</pre>
</div>
<p> </p>
<p><strong><span style="font-family: 幼圆; font-size: 18pt">获得插入行的ID</span></strong></p>
<p><span style="font-size: 18px"><span style="font-family: 幼圆">如果你正在插入一行到一个具有自动递增主键的表中,你可以像这样检索插入id:</span></span></p>
<p> </p>
<div class="cnblogs_code">
<pre>connection.query(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">INSERT INTO posts SET ?</span><span style="color: rgba(128, 0, 0, 1)">'</span>, {title: <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">test</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">}, function (error, results, fields) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (error) <span style="color: rgba(0, 0, 255, 1)">throw</span><span style="color: rgba(0, 0, 0, 1)"> error;
console.log(results.insertId);
});</span></pre>
</div>
<p> </p>
<p><span style="font-family: 幼圆; font-size: 18px">当处理大数字(超过JavaScript数字精度限制)时,您应该考虑启用supportBigNumbers选项,使其能够将插入id读取为字符串,否则将抛出错误。</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">在从数据库中获取较大的数字时也需要此选项,否则由于精度限制,您将得到四舍五入到数百或数千的值。</span></p>
<p> </p>
<p><strong><span style="font-family: 幼圆; font-size: 18pt">获得受影响行的数目</span></strong></p>
<p><span style="font-size: 18px"><span style="font-family: 幼圆">你可以获得由于插入,更新或者删除语句而受影响的行数:</span></span></p>
<p> </p>
<div class="cnblogs_code">
<pre>connection.query(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">DELETE FROM posts WHERE title = "wrong"</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, function (error, results, fields) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (error) <span style="color: rgba(0, 0, 255, 1)">throw</span><span style="color: rgba(0, 0, 0, 1)"> error;
console.log(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">deleted </span><span style="color: rgba(128, 0, 0, 1)">'</span> + results.affectedRows + <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)"> rows</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">);
})</span></pre>
</div>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p><span style="font-family: 幼圆; font-size: 18pt"><strong>获得受已改变行的数目</strong></span></p>
<p><span style="font-family: 幼圆; font-size: 18px">你可以获得由于更新语句而改变的行的数目。</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">这不同于受影响的行,因为已改变行的数目不包括值未发生变化的行的行数。</span></p>
<p> </p>
<div class="cnblogs_code">
<pre>connection.query(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">UPDATE posts SET ...</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, function (error, results, fields) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (error) <span style="color: rgba(0, 0, 255, 1)">throw</span><span style="color: rgba(0, 0, 0, 1)"> error;
console.log(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">changed </span><span style="color: rgba(128, 0, 0, 1)">'</span> + results.changedRows + <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)"> rows</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">);
})</span></pre>
</div>
<p> </p>
<p> </p>
<p><strong><span style="font-family: 幼圆; font-size: 18pt">获得连接ID</span></strong></p>
<p><span style="font-size: 18px"><span style="font-family: 幼圆">您可以使用threadId属性获得给定连接的MySQL连接ID(“thread ID”)。</span></span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">connection.connect(function(err) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (err) <span style="color: rgba(0, 0, 255, 1)">throw</span><span style="color: rgba(0, 0, 0, 1)"> err;
console.log(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">connected as id </span><span style="color: rgba(128, 0, 0, 1)">'</span> +<span style="color: rgba(0, 0, 0, 1)"> connection.threadId);
});</span></pre>
</div>
<p> </p>
<p> </p>
<p><span style="font-family: 幼圆; font-size: 18pt"><strong>并行执行查询</strong></span></p>
<p><span style="font-family: 幼圆; font-size: 18px">MySQL协议是顺序的,这意味着您需要多个连接来并行执行查询。您可以使用一个连接池来管理连接,一种简单的方法是为每个传入的http请求创建一个连接。</span></p>
<p> </p>
<p><strong><span style="font-family: 幼圆; font-size: 18pt">流媒体查询行</span></strong></p>
<p><span style="font-size: 18px"><span style="font-family: 幼圆">有时,您可能希望选择大量的行,并在接收到它们时处理它们。可以这样做:</span></span></p>
<p> </p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> query = connection.query(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">SELECT * FROM posts</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">);
query
.on(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">error</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, function(err) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Handle error, an 'end' event will be emitted after this as well</span>
<span style="color: rgba(0, 0, 0, 1)">})
.on(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">fields</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, function(fields) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> the field packets for the rows to follow</span>
<span style="color: rgba(0, 0, 0, 1)">})
.on(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">result</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, function(row) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Pausing the connnection is useful if your processing involves I/O</span>
<span style="color: rgba(0, 0, 0, 1)"> connection.pause();
processRow(row, function() {
connection.resume();
});
})
.on(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">end</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, function() {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> all rows have been received</span>
});</pre>
</div>
<p> </p>
<p><span style="font-family: 幼圆; font-size: 18px">关于上面的例子,请注意以下几点:</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">通常,在开始使用pause()限制连接之前你一定希望收到相当数量的行。这个数字取决于行的数量和大小。调用pause()和resume()操作底层socket和解析器。你完全可以保证调用pause()后result事件就不会再触发。</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">在使用流式数据时,你一定不能给query()方法提供回调函数。</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">非常重要的一点是,不要让结果停留太长时间,否则可能会遇到这样的错误:Connection lost:服务器关闭了连接。这个时间限制由MySQL服务器上的net_write_timeout设置决定。</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">此外,您可能有兴趣知道,目前还不可能流化单个行列,它们将总是被完全缓冲。如果你有一个很好的用于在MySQL之间传输大字段的用例,我很乐意听取你的想法和贡献。</span></p>
<p><strong><span style="font-family: 幼圆; font-size: 18px">带有流的管道结果</span></strong></p>
<p> </p>
<p><span style="font-family: 幼圆; font-size: 18px">query对象提供了一个方便的方法. Stream (),它将查询事件包装到一个可读的Stream对象中。该流可以很容易地被输送到下游,并基于下游拥塞和可选的highWaterMark提供自动暂停/恢复。流的objectMode参数被设置为true并且不能更改(如果你需要一个字节流,你将需要使用一个转换流,例如objstream)。</span></p>
<p> </p>
<p><span style="font-family: 幼圆; font-size: 18px">例如,将查询结果管道到另一个流(最大缓冲区为5个对象)很简单:</span></p>
<div class="cnblogs_code">
<pre>connection.query(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">SELECT * FROM posts</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
.stream({highWaterMark: </span><span style="color: rgba(128, 0, 128, 1)">5</span><span style="color: rgba(0, 0, 0, 1)">})
.pipe(...);</span></pre>
</div>
<p> </p>
<p><strong><span style="font-family: 幼圆; font-size: 18pt">多语句查询</span></strong></p>
<p><span style="font-size: 18px"><span style="font-family: 幼圆">出于安全原因,多语句查询时禁止的。(如果值未正确地转义这会允许sql注入攻击)。要使用此功能,您必须为您的连接启用它:</span></span></p>
<p> </p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> connection = mysql.createConnection({multipleStatements: <span style="color: rgba(0, 0, 255, 1)">true</span>});</pre>
</div>
<p> </p>
<p><span style="font-family: 幼圆; font-size: 18px">一旦开启,你可以像这样执行多语句查询:</span></p>
<div class="cnblogs_code">
<pre><span style="font-family: 幼圆; font-size: 14px">connection.query(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">SELECT 1; SELECT 2</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, function (error, results, fields) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (error) <span style="color: rgba(0, 0, 255, 1)">throw</span><span style="color: rgba(0, 0, 0, 1)"> error;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> `results` is an array with one element for every statement in the query:</span>
console.log(results[<span style="color: rgba(128, 0, 128, 1)">0</span>]); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> [{1: 1}]</span>
console.log(results[<span style="color: rgba(128, 0, 128, 1)">1</span>]); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> [{2: 2}]</span>
});</span></pre>
</div>
<p><span style="font-family: 幼圆; font-size: 18px">此外,你还可以流式显示多个语句查询的结果:</span></p>
<div class="cnblogs_code">
<pre><span style="font-family: 幼圆; font-size: 16px"><span style="color: rgba(0, 0, 255, 1)">var</span> query = connection.query(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">SELECT 1; SELECT 2</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">);
query
.on(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">fields</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, function(fields, index) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> the fields for the result rows that follow</span>
<span style="color: rgba(0, 0, 0, 1)">})
.on(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">result</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, function(row, index) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> index refers to the statement this result belongs to (starts at 0)</span>
});</span></pre>
</div>
<p><span style="font-family: 幼圆; font-size: 18px">如果查询中的某个语句导致错误,则产生的error对象包含一个err.index属性,该属性告诉您是哪条语句导致了错误。当出现错误时,MySQL也将停止执行任何剩余的语句。</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">请注意,流多语句查询的接口是实验性的,我期待对它的反馈。</span></p>
<p> </p>
<p><strong><span style="font-family: 幼圆; font-size: 18pt">存储过程</span></strong></p>
<p><span style="font-size: 18px"><span style="font-family: 幼圆">您可以从查询中调用存储过程,就像使用任何其他mysql驱动程序一样。如果存储过程产生多个结果集,它们将以与多个语句查询的结果相同的方式向您公开。</span></span></p>
<p> </p>
<p><strong><span style="font-family: 幼圆; font-size: 18pt">使用重叠列名进行连接</span></strong></p>
<p><span style="font-family: 幼圆; font-size: 18px">执行join时,很可能会得到具有重叠列名的结果集。</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">默认情况下,node-mysql会按照从MySQL接收列的顺序覆盖冲突的列名,导致接收到的一些值不可用。</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">然而,你也可以指定你的列像这样嵌套在表名下面:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> options = {sql: <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">...</span><span style="color: rgba(128, 0, 0, 1)">'</span>, nestTables: <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">};
connection.query(options, function (error, results, fields) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (error) <span style="color: rgba(0, 0, 255, 1)">throw</span><span style="color: rgba(0, 0, 0, 1)"> error;
</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)"> results will be an array like this now:
[{
table1: {
fieldA: '...',
fieldB: '...',
},
table2: {
fieldA: '...',
fieldB: '...',
},
}, ...]
</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
});</span></pre>
</div>
<p><span style="font-family: 幼圆; font-size: 18px">或者使用字符串分隔符来合并结果:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> options = {sql: <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">...</span><span style="color: rgba(128, 0, 0, 1)">'</span>, nestTables: <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">_</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">};
connection.query(options, function (error, results, fields) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (error) <span style="color: rgba(0, 0, 255, 1)">throw</span><span style="color: rgba(0, 0, 0, 1)"> error;
</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)"> results will be an array like this now:
[{
table1_fieldA: '...',
table1_fieldB: '...',
table2_fieldA: '...',
table2_fieldB: '...',
}, ...]
</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
});</span></pre>
</div>
<p><strong><span style="font-family: 幼圆; font-size: 18pt">Transactions</span></strong></p>
<p><span style="font-family: 幼圆; font-size: 18px">连接提供简单的事务支持:</span></p>
<p> </p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">connection.beginTransaction(function(err) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (err) { <span style="color: rgba(0, 0, 255, 1)">throw</span><span style="color: rgba(0, 0, 0, 1)"> err; }
connection.query(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">INSERT INTO posts SET title=?</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, title, function (error, results, fields) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (error) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> connection.rollback(function() {
</span><span style="color: rgba(0, 0, 255, 1)">throw</span><span style="color: rgba(0, 0, 0, 1)"> error;
});
}
</span><span style="color: rgba(0, 0, 255, 1)">var</span> log = <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Post </span><span style="color: rgba(128, 0, 0, 1)">'</span> + results.insertId + <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)"> added</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
connection.query(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">INSERT INTO log SET data=?</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, log, function (error, results, fields) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (error) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> connection.rollback(function() {
</span><span style="color: rgba(0, 0, 255, 1)">throw</span><span style="color: rgba(0, 0, 0, 1)"> error;
});
}
connection.commit(function(err) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (err) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> connection.rollback(function() {
</span><span style="color: rgba(0, 0, 255, 1)">throw</span><span style="color: rgba(0, 0, 0, 1)"> err;
});
}
console.log(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">success!</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">);
});
});
});
});</span></pre>
</div>
<p> </p>
<p><span style="font-family: 幼圆; font-size: 18px">请注意,beginTransaction(), commit()和rollback()只是简单的函数,分别执行开始事务,提交和回滚命令。如MySQL文档中所述,MySQL中的许多命令都可能导致隐式提交,理解这一点很重要。</span></p>
<p> </p>
<p><strong><span style="font-family: 幼圆; font-size: 18pt">Ping</span></strong></p>
<p><span style="font-size: 18px"><span style="font-family: 幼圆">可以通过connection.ping()方法发送一个ping包到该连接上。此方法将向服务器发送一个ping包,当服务器响应时,回调将触发。如果发生错误,回调函数将触发一个error参数。</span></span></p>
<p> </p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">connection.ping(function (err) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (err) <span style="color: rgba(0, 0, 255, 1)">throw</span><span style="color: rgba(0, 0, 0, 1)"> err;
console.log(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Server responded to ping</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">);
})</span></pre>
</div>
<p> </p>
<p> </p>
<p><span style="font-size: 18pt"><strong><span style="font-family: 幼圆">超时</span></strong></span></p>
<p><span style="font-family: 幼圆; font-size: 18px">每个操作都有一个可选的不活动超时选项。这允许您为操作指定适当的超时。需要注意的是,这些超时不是MySQL协议的一部分,而是通过客户端的超时操作。这意味着,当达到超时时,发生超时的连接将被销毁,并且无法执行进一步的操作。</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Kill query after 60s</span>
connection.query({sql: <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">SELECT COUNT(*) AS count FROM big_table</span><span style="color: rgba(128, 0, 0, 1)">'</span>, timeout: <span style="color: rgba(128, 0, 128, 1)">60000</span><span style="color: rgba(0, 0, 0, 1)">}, function (error, results, fields) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (error && error.code === <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">PROTOCOL_SEQUENCE_TIMEOUT</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 0, 255, 1)">throw</span> <span style="color: rgba(0, 0, 255, 1)">new</span> Error(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">too long to count table rows!</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">);
}
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (error) {
</span><span style="color: rgba(0, 0, 255, 1)">throw</span><span style="color: rgba(0, 0, 0, 1)"> error;
}
console.log(results[</span><span style="color: rgba(128, 0, 128, 1)">0</span>].count + <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)"> rows</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">);
});</span></pre>
</div>
<p> </p>
<p><strong><span style="font-family: 幼圆; font-size: 18pt">错误处理</span></strong></p>
<p><span style="font-family: 幼圆; font-size: 18px">该模块提供了一种一致的错误处理方法,为了编写可靠的应用程序,您应该仔细检查该方法。</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">该模块创建的大多数错误都是JavaScript Error对象的实例。此外,它们通常带有两个额外的属性:</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">err.code:字符串。包含mysql服务器的错误符号,如果错误是mysql服务器:例如ER_ACCESS_DENIED_ERROR;如果是node.js错误,则为node.js错误代码,如ECONNREFUSED。或者一个内部错误代码PROTOCOL_CONNECTION_LOST.</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">err.errno:数字。mysql服务器的错误号。只能被mysql服务器错误填充。</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">err.fatal:boolean。指示此错误是否是连接对象的终止。如果错误不是来自MySQL协议操作,则不会定义此属性。</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">err.sql:字符串。包含失败查询的完整SQL。当使用更高级的接口(如生成查询的ORM)时,这可能非常有用。</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">err.sqlState:字符串,包含5个字符的sqlState值。只能被MySQL服务器错误填充。</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">err.sqlMessage:字符串,包含提供错误的文本描述的消息字符串。只能被MySQL服务器错误填充。</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">致命错误会传递到所有挂起的回调。在下面的示例中,当试图连接到一个无效端口时,将触发一个致命错误。因此,error对象会被传递到两个挂起的回调中:</span></p>
<div class="cnblogs_code">
<pre><span style="font-family: 幼圆; font-size: 16px"><span style="color: rgba(0, 0, 255, 1)">var</span> connection = require(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">mysql</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">).createConnection({
port: </span><span style="color: rgba(128, 0, 128, 1)">84943</span>, <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> WRONG PORT</span>
<span style="color: rgba(0, 0, 0, 1)">});
connection.connect(function(err) {
console.log(err.code); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 'ECONNREFUSED'</span>
console.log(err.fatal); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> true</span>
<span style="color: rgba(0, 0, 0, 1)">});
connection.query(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">SELECT 1</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, function (error, results, fields) {
console.log(error.code); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 'ECONNREFUSED'</span>
console.log(error.fatal); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> true</span>
});</span></pre>
</div>
<p><span style="font-family: 幼圆; font-size: 18px">但是正常的错误只提交给他们所属的错误,所以在以下例子种,只有第一个回调收到了错误,第二个正常执行:</span></p>
<div class="cnblogs_code">
<pre><span style="font-family: 幼圆; font-size: 15px">connection.query(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">USE name_of_db_that_does_not_exist</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, function (error, results, fields) {
console.log(error.code); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 'ER_BAD_DB_ERROR'</span>
<span style="color: rgba(0, 0, 0, 1)">});
connection.query(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">SELECT 1</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, function (error, results, fields) {
console.log(error); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> null</span>
console.log(results.length); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 1</span>
});</span></pre>
</div>
<p><span style="font-family: 幼圆; font-size: 18px">最后但并非最不重要的:如果发生了致命错误且没有挂起的回调,或者发生了没有回调的正常错误,则该错误将作为connection对象上的'error'事件发出。下面的例子演示了这一点:</span></p>
<div class="cnblogs_code">
<pre><span style="font-family: 幼圆; font-size: 14px">connection.on(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">error</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, function(err) {
console.log(err.code); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 'ER_BAD_DB_ERROR'</span>
<span style="color: rgba(0, 0, 0, 1)">});
connection.query(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">USE name_of_db_that_does_not_exist</span><span style="color: rgba(128, 0, 0, 1)">'</span>);</span></pre>
</div>
<p><span style="font-family: 幼圆; font-size: 18px">注意:'error'事件在node中是特殊的。如果它们在没有附加侦听器的情况下发生,则会打印堆栈跟踪并杀死进程。</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">tl;dr:这个模块不希望您处理静默故障。你应该总是为你的方法调用提供回调。如果你想忽略这个建议并抑制未处理的错误,你可以这样做:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> I am Chuck Norris:</span>
connection.on(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">error</span><span style="color: rgba(128, 0, 0, 1)">'</span>, function() {});</pre>
</div>
<p><strong><span style="font-family: 幼圆; font-size: 18pt">异常安全的</span></strong></p>
<p><span style="font-family: 幼圆; font-size: 18px">此模块是异常安全的。这意味着你可以继续使用它,即使你的一个回调函数抛出一个错误,你正在用'uncaughtException'或域捕捉。</span></p>
<h2><span style="font-family: 幼圆; font-size: 18pt">类型规划</span></h2>
<p><span style="font-family: 幼圆; font-size: 18px">为了方便,这个驱动程序将默认地将mysql类型转换为原生JavaScript类型。存在以下映射关系:</span></p>
<h3>Number</h3>
<ul>
<li>TINYINT</li>
<li>SMALLINT</li>
<li>INT</li>
<li>MEDIUMINT</li>
<li>YEAR</li>
<li>FLOAT</li>
<li>DOUBLE</li>
</ul>
<h3>Date</h3>
<ul>
<li>TIMESTAMP</li>
<li>DATE</li>
<li>DATETIME</li>
</ul>
<h3>Buffer</h3>
<ul>
<li>TINYBLOB</li>
<li>MEDIUMBLOB</li>
<li>LONGBLOB</li>
<li>BLOB</li>
<li>BINARY</li>
<li>VARBINARY</li>
<li>BIT (最后一个字节将根据需要填充0比特) 说明二进制字符集中的文本作为缓冲区返回,而不是字符串。
<h3>String(二进制字符集中的文本作为缓冲区返回,而不是字符串。)</h3>
</li>
<li></li>
<ul>
<li>CHAR</li>
<li>VARCHAR</li>
<li>TINYTEXT</li>
<li>MEDIUMTEXT</li>
<li>LONGTEXT</li>
<li>TEXT</li>
<li>ENUM</li>
<li>SET</li>
<li>DECIMAL (可能超过浮点精度)</li>
<li>BIGINT (可能超过浮点精度)</li>
<li>TIME (可以映射到日期,但将设置成什么日期?)</li>
<li>GEOMETRY (从未使用过,如果使用过请联系)</li>
</ul>
</ul>
<p> </p>
<p><span style="font-family: 幼圆; font-size: 18px">不建议禁用类型转换(可能会在将来消失/更改),但目前你可以在任意一个连接上这样做:</span></p>
<div class="cnblogs_code">
<pre><span style="font-family: 幼圆; font-size: 14px"><span style="color: rgba(0, 0, 255, 1)">var</span> connection = require(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">mysql</span><span style="color: rgba(128, 0, 0, 1)">'</span>).createConnection({typeCast: <span style="color: rgba(0, 0, 255, 1)">false</span>});</span></pre>
</div>
<p><span style="font-family: 幼圆; font-size: 18px">或者查询时:</span></p>
<div class="cnblogs_code">
<pre><span style="font-family: 幼圆; font-size: 14px"><span style="color: rgba(0, 0, 255, 1)">var</span> options = {sql: <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">...</span><span style="color: rgba(128, 0, 0, 1)">'</span>, typeCast: <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">};
</span><span style="color: rgba(0, 0, 255, 1)">var</span> query =<span style="color: rgba(0, 0, 0, 1)"> connection.query(options, function (error, results, fields) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (error) <span style="color: rgba(0, 0, 255, 1)">throw</span><span style="color: rgba(0, 0, 0, 1)"> error;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ...</span>
});</span></pre>
</div>
<p><strong><span style="font-family: 幼圆; font-size: 18px">自定义类型规划</span></strong></p>
<p><span style="font-family: 幼圆; font-size: 18px">您还可以自己传递一个函数和处理类型转换。您将得到一些列信息,如数据库、表和名称,以及类型和长度。如果您只是想将自定义类型转换应用到特定类型,您可以这样做,然后回退到默认类型。</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">该函数提供了两个参数field和next,并期望通过field对象调用解析器函数返回给定字段的值。</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">field参数是一个Field对象,包含关于需要解析的字段的数据。以下是Field对象的一些属性:</span></p>
<p><span style="font-family: 幼圆"><span style="font-size: 18px">db:来自数据库字符串的字段</span></span></p>
<p><span style="font-family: 幼圆"><span style="font-size: 18px">table:来自表字符串的字段</span></span></p>
<p><span style="font-family: 幼圆"><span style="font-size: 18px">name:字段名字符串</span></span></p>
<p><span style="font-family: 幼圆"><span style="font-size: 18px">type:所有大写的字段类型的字符串</span></span></p>
<p><span style="font-family: 幼圆"><span style="font-size: 18px">length:字段长度,有数据库给出。</span></span></p>
<p> </p>
<p> </p>
<p><span style="font-family: 幼圆; font-size: 18px">下一个参数是一个函数,当被调用时,它将返回给定字段的默认类型转换。</span></p>
<p> </p>
<p><span style="font-family: 幼圆; font-size: 18px">当获取字段数据时,下面的更有用的方法出现在字段对象上:</span></p>
<p> </p>
<p><span style="font-family: 幼圆; font-size: 18px">.string() -将字段解析为字符串。</span></p>
<p> </p>
<p><span style="font-family: 幼圆; font-size: 18px">. Buffer() -将字段解析为缓冲区。</span></p>
<p> </p>
<p><span style="font-family: 幼圆; font-size: 18px">.geometry() -将该字段解析为一个几何值。</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">MySQL协议是基于文本的协议。这意味着在连接过程中,所有字段类型都表示为字符串,这就是为什么field对象上只有类似字符串的函数可用。根据类型信息(如INT),类型转换应该将字符串字段转换为不同的JavaScript类型(如数字)。</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">下面是一个将TINYINT(1)转换为布尔值的例子:</span></p>
<div class="cnblogs_code">
<pre>connection =<span style="color: rgba(0, 0, 0, 1)"> mysql.createConnection({
typeCast: function (field, next) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (field.type === <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">TINY</span><span style="color: rgba(128, 0, 0, 1)">'</span> && field.length === <span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span> (field.<span style="color: rgba(0, 0, 255, 1)">string</span>() === <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">1</span><span style="color: rgba(128, 0, 0, 1)">'</span>); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 1 = true, 0 = false</span>
} <span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> next();
}
}
});</span></pre>
</div>
<p> </p>
<p><span style="font-family: 幼圆; font-size: 18px">注意:您必须在自定义类型转换回调中使用这三个字段函数中的一个来调用解析器。它们只能被调用一次。</span></p>
<p> </p>
<p> </p>
<p><strong><span style="font-family: 幼圆; font-size: 18pt">调试和报告问题</span></strong></p>
<p> </p>
<p><span style="font-family: 幼圆; font-size: 18px">如果你遇到了问题,打开连接的调试模式可能会有帮助:</span></p>
<div class="cnblogs_code">
<pre><span style="font-family: 幼圆; font-size: 18px"><span style="color: rgba(0, 0, 255, 1)">var</span> connection = mysql.createConnection({debug: <span style="color: rgba(0, 0, 255, 1)">true</span>});</span></pre>
</div>
<p><span style="font-family: 幼圆; font-size: 18px">这将在标准输出上打印所有传入和传出的数据包。你也可以通过传递一个类型数组来限制对数据包类型的调试:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> connection = mysql.createConnection({debug: [<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">ComQueryPacket</span><span style="color: rgba(128, 0, 0, 1)">'</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">RowDataPacket</span><span style="color: rgba(128, 0, 0, 1)">'</span>]});</pre>
</div>
<p><span style="font-family: 幼圆; font-size: 18px">将调试限制在查询报文和数据报文上。</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">如果这没有帮助,请随意打开GitHub问题。一个好的GitHub问题会有:</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">重现问题所需的最少代码量(如果可能的话)</span></p>
<p><span style="font-family: 幼圆; font-size: 18px">尽可能多的调试输出和关于环境(mysql版本、节点版本、os等)的信息。</span></p>
<p> </p>
<p><span style="font-family: 幼圆; font-size: 18px">finish。愉快的参与到基于node.js的mysql开发叭~</span></p>
<p> </p><br><br>
来源:https://www.cnblogs.com/tanyui/p/14342321.html
頁:
[1]