在 Php 中 , PDO :: Exec ()是一个用于执行不返回结果集的 SQL 语句的方法 , 如INSERT 、 MISE À JOUR 、 DELETE等。尽管 PDO 提供了一个统一的接口来操作多种数据库 , 但在不同的数据库系统之间 , 其行为存在一些微妙但关键的差异。本文将深入解析PDO :: EXEC ()在 MySQL 、 PostgreSQL 和 SQLITE 三种数据库中的表现差异 , 帮助开发者写出更具兼容性的跨库代码。
PDO :: Exec (instruction String $)返回一个整数值 , 表示受影响的行数。若发生错误 , 则返回FAUX并可通过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>-></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 > NOW() - INTERVAL 30 DAY"</span></span><span>);
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">"影响的行数: <span class="hljs-subst">$count</span></span></span><span>";
</span></span>
在 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>-></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 = 1的nom原本就是John , 那么返回的影响行数为0 , 因为没有真正的数据变更。
Postgresql 在执行PDO :: exec ()时返回的也是影响行数 , 但有一个小区别 :默认开启事务机制。如果你没有显式提交事务 , 更新可能并未真正写入数据库。
此外 , 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>-></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 与其他两者最大的不同在于其轻量级实现。虽然也返回受影响的行数 , 但有些操作表现得不同:
没有类型强校验: 可能导致看起来 可能导致看起来 可能导致看起来 无变化 无变化 无变化 的字段也算作已更新。
空事务优化少: 即使值相同 , 某些情况下也返回 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>-></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>
即便用户的Courriel没有变化 , sqlite 在某些版本中仍可能返回1 , 这在逻辑判断中需要格外注意。
数据库 | 相同行数计算规则 | 特殊注意事项 |
---|---|---|
Mysql | 值实际变更时才计入 | 忽略未变更字段 , 不计入影响行数 |
Postgresql | 计入触发器、级联等逻辑行数 | 默认事务机制 , 需手动提交 |
Sqlite | 可能统计未变更字段 | 类型宽松 , 行为更像是 «尝试执行» |
不依赖影响行数判断逻辑控制事务流。
在多数据库环境中 , 考虑使用Sélectionner查询先对比变更内容 , 避免误判。
明确事务开始与提交 , 特别是在 postgresql 中。
虽然PDO :: exec ()提供了一种通用接口 , 但背后的数据库差异决定了其行为并不总是完全一致。理解这些底层细节 , 才能写出健壮、可移植的 Php 程序。对于复杂操作 , 考虑封装统一行为或使用数据库抽象层 (如 Doctrine) 是一个更好的选择。