2

我在 MySQL 中有一个包含各种 VARCHAR 字段的表。我想通过 PHP 从表单中插入一些用户数据。显然,如果我知道 PHP 中的字段长度,我可以用substr(). 但是这种违反 DRY(存储在 MySQL 中的字段长度并作为我的 PHP 脚本中的常量)。有没有办法让我配置一个 INSERT 以便它自动切断过长的字符串,而不是失败?

编辑:当我的字符串过长时,它在 PHP/PDO 中失败(或至少导致异常)。不知道我必须在 PHP/PDO 中做什么,所以它做正确的事。

编辑2:呃。这是错误的方法;即使我让它在 INSERT 上正常工作,如果我想检查重复的字符串,它也不会正确匹配。

4

3 回答 3

9

实际上,MySQL 默认将字符串截断为列宽。它会生成警告,但允许插入。

mysql> create table foo (str varchar(10));
mysql> insert into foo values ('abcdefghijklmnopqrstuvwxyz');
Query OK, 1 row affected, 1 warning (0.00 sec)
mysql> show warnings;
+---------+------+------------------------------------------+
| Level   | Code | Message                                  |
+---------+------+------------------------------------------+
| Warning | 1265 | Data truncated for column 'str' at row 1 | 
+---------+------+------------------------------------------+
mysql> select * from foo;
+------------+
| str        |
+------------+
| abcdefghij | 
+------------+

如果您设置严格的 SQL 模式,它会将警告变为错误并拒绝插入。


回复您的评论:SQL 模式是 MySQL 服务器配置。它可能不是导致它的 PDO,但另一方面它是可能的,因为任何客户端都可以为其会话设置 SQL 模式。

您可以使用以下语句检索当前的全局或会话 sql_mode 值:

SELECT @@GLOBAL.sql_mode;
SELECT @@SESSION.sql_mode;

默认值应为空字符串(未设置模式)。您可以使用 mysqld 选项或使用语句在my.cnf文件中设置 SQL 模式。--sql-modeSET

更新:MySQL 5.7 及更高版本默认设置严格模式。见https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html

于 2009-06-19T17:05:11.127 回答
0

您可以查询 information_schema 以获取列的长度并在插入之前使用该数据进行截断,但这比必要的开销更大。只需为此语句关闭严格的 SQL 模式:

SET @prev_mode = @@sql_mode;
SET sql_mode = '';
INSERT blah....;
SET sql_mode = @prev_mode;
于 2009-06-19T17:52:36.620 回答
0

您可以使用列元数据来检查字符串长度。(关于 PDOStatement->getColumnMeta 的 PHP 手册

以这种方式获取整个表的元数据

$query = $conn->query("SELECT * FROM places");
$numcols = $query->columnCount();

$tablemeta = array();
for ($i = 0; $i < $numcols; $i++) {
    $colmeta = $query->getColumnMeta($i);
    $tablemeta[$colmeta['name']] = $colmeta;
}
于 2009-07-02T17:48:42.237 回答