現在の位置: ホーム> 最新記事一覧> PDO :: ExecはMySQL、PostgreSQL、およびSQLiteでどのように機能しますか?横断節微分分析

PDO :: ExecはMySQL、PostgreSQL、およびSQLiteでどのように機能しますか?横断節微分分析

gitbox 2025-06-12

php中、 pdo :: exec()个用于执不返结果集的sql

基本行为:pdo :: exec()

pdo :: exec(String $ statement)返回一个整数值、表示受影响的行数。若发生错误、则返回false并可通过pdo:: errorinfo()获取错误信息。

 <span><span><span class="hljs-variable">$db</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-title function_ invoke__">PDO</span></span><span>(</span><span><span class="hljs-string">'mysql:host=localhost;dbname=test'</span></span><span>, </span><span><span class="hljs-string">'user'</span></span><span>, </span><span><span class="hljs-string">'pass'</span></span><span>);
</span><span><span class="hljs-variable">$count</span></span><span> = </span><span><span class="hljs-variable">$db</span></span><span>-&gt;</span><span><span class="hljs-title function_ invoke__">exec</span></span><span>(</span><span><span class="hljs-string">"UPDATE users SET status = 'active' WHERE last_login &gt; NOW() - INTERVAL 30 DAY"</span></span><span>);
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">"&#24433;&#21709;&#30340;&#34892;&#25968;: <span class="hljs-subst">$count</span></span></span><span>";
</span></span>

mysql中的表现

mysql中、 pdo :: exec()的行为相对直观。只要sql执行成功、它就会返回受影响的行数。这里的“受影响”是指值实际发生变化的行。

例如:

 <span><span><span class="hljs-variable">$db</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-title function_ invoke__">PDO</span></span><span>(</span><span><span class="hljs-string">"mysql:host=gitbox.net;dbname=demo"</span></span><span>, </span><span><span class="hljs-string">"user"</span></span><span>, </span><span><span class="hljs-string">"pass"</span></span><span>);
</span><span><span class="hljs-variable">$db</span></span><span>-&gt;</span><span><span class="hljs-title function_ invoke__">exec</span></span><span>(</span><span><span class="hljs-string">"UPDATE users SET name = 'John' WHERE id = 1"</span></span><span>);
</span></span>

如果用户id = 1name原本就是ジョン、那么返回的影响行数为0 、因为没有真正的数据变更。

postgreSql中的表现

postgreSql

此外、postgreSql 会将视图、触发器等逻辑更新的结果计入影响行数。

 <span><span><span class="hljs-variable">$db</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-title function_ invoke__">PDO</span></span><span>(</span><span><span class="hljs-string">"pgsql:host=gitbox.net;dbname=demo"</span></span><span>, </span><span><span class="hljs-string">"user"</span></span><span>, </span><span><span class="hljs-string">"pass"</span></span><span>);
</span><span><span class="hljs-variable">$db</span></span><span>-&gt;</span><span><span class="hljs-title function_ invoke__">exec</span></span><span>(</span><span><span class="hljs-string">"UPDATE products SET price = price * 1.1 WHERE category = 'Books'"</span></span><span>);
</span></span>

如果启用了触发器(如修改库存表)、返回的行数将反映所有级联影响的记录数。

sqlite中的表现

sqlite与其他两者最大的不同在于其轻量级实现。虽然也返回受影响的行数、但有些操作表现得不同:

  1. 没有类型强校验:可能导致看起来“无变化”的字段也算作已更新。

  2. 空事务优化少:即使值相同、某些情况下也返回1行被影响。

 <span><span><span class="hljs-variable">$db</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-title function_ invoke__">PDO</span></span><span>(</span><span><span class="hljs-string">"sqlite:/path/to/gitbox.net-demo.db"</span></span><span>);
</span><span><span class="hljs-variable">$count</span></span><span> = </span><span><span class="hljs-variable">$db</span></span><span>-&gt;</span><span><span class="hljs-title function_ invoke__">exec</span></span><span>(</span><span><span class="hljs-string">"UPDATE users SET email = '[email protected]' WHERE id = 5"</span></span><span>);
</span></span>

即便用户的メール没有变化、sqlite在某些版本中仍可能返回1 、这在逻辑判断中需要格外注意。

小结:跨数据库使用pdo :: exec()的建议

数据库相同行数计算规则特殊注意事项
mysql值实际变更时才计入忽略未变更字段、不计入影响行数
postgreSql计入触发器、级联等逻辑行数默认事务机制、需手动提交
sqlite可能统计未变更字段类型宽松、行为更像是「尝试执行」

最佳实践

  • 不依赖影响行数判断逻辑控制事务流。

  • 在多数据库环境中、考虑使用select查询先对比变更内容、避免误判。

  • 明确事务开始与提交、特别是在postgresql中。

结语

pdo :: exec()提供了一种通用接口、但背后的数据库差异决定了其行为并不总是完全一致。理解这些底层细节、才能写出健壮、可移植的 php程序。对于复杂操作、考虑封装统一行为或使用数据库抽象层(如教義)是一个更好的选择。