【问题标题】:PDO cannot compare mysql ENUM using integers in prepared statementsPDO 无法在准备好的语句中使用整数比较 mysql ENUM
【发布时间】:2010-09-02 08:59:28
【问题描述】:

我正在使用 PDO 和准备好的语句,但是当将 ENUM 字段与整数进行比较时,我似乎无法得到任何结果。

例子:

$db = new PDO('mysql:host=localhost;dbname=****', '***', '***');
$s = $db->prepare('SELECT id FROM t2 WHERE lang = ?');

$s->execute(array('en')); // Works              
print_r($s->fetchAll());

$s->execute(array(2)); // Does not work            
print_r($s->fetchAll());

我正在针对这张表进行测试:

DROP TABLE IF EXISTS t2;
CREATE TABLE t2 (
  id int(10) NOT NULL AUTO_INCREMENT,
  lang enum('no','en','fr') NOT NULL,
  PRIMARY KEY (id)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;
INSERT INTO  t2 (id, lang) VALUES (NULL , 'en');

知道如何让它发挥作用吗?

我正在转换为 PDO,我不想重写我的应用程序中的所有常量、枚举和查询:(

【问题讨论】:

  • 好的。我会给自己挖一个大坑,直到所有的 ENUM 都被聪明的外键替换后才会出来。 叹息

标签: php sql mysql enums pdo


【解决方案1】:

2 不是有效的 ENUM 元素。就这么简单。

当您执行lang = 2 时,它在原始 MySQL 中工作的原因是它暴露了列表的底层存储机制(基本上它只是一个规范化的值,但是 ENUM 列对您隐藏了规范化)。

我建议不要尝试这样做。 MySQL 隐藏实现是有原因的。意识到使用2 进行比较只不过是magic number...

【讨论】:

    【解决方案2】:

    语言不应该是枚举,事实上不要使用枚举,而是使用单独的查找/类型表:

    create table languages
    (
      lang_id tinyint unsigned not null auto_increment primary key,
      name varchar(255) unique not null
    )
    engine=innodb;
    
    create table customers
    (
      cust_id int unsigned not null auto_increment primary key,
      lang_id tinyint unsigned not null,
      foreign key (lang_id) references languages(lang_id)
    )
    engine=innodb;
    

    您还应该知道,向 ENUM 定义添加新值将需要 MySQL 重建整个表 - 对于大型表来说不是最佳的!!

    【讨论】:

    • 谢谢! ircmaxell 得到了原因,而你得到了方法。我爱你们。
    【解决方案3】:

    推理:
    我同意你不应该通过枚举索引选择任何东西,甚至根本不需要使用数据库枚举,但总是有例外和特殊情况。
    就我而言,它是一个遗留系统,当然要被新系统取代,但这至少需要一年时间,甚至可能更长。 对遗留系统的任何数据库更改都会产生很大影响,我们尽量将其保持在最低限度。我们确实有一个包含用户组的小表,并且组 ID 也设置为枚举。所以是的,添加一个组还需要向该表的 id 列添加另一个枚举值。
    我不知道这是怎么来的,我也不质疑它,我只需要处理它,直到我们可以完全替换它。

    我想提供一个简单的用户管理,因为现在任何用户更改都必须经过一个漫长的过程,这导致开发人员直接在数据库中进行更改。用户组按枚举索引分层,我想过滤管理中的可用组,使其小于或等于当前登录的用户组。

    长话短说;为了在准备好的声明中完成这项工作,我这样做了:

    SELECT `groups`.*, `groups`.`id`+0 AS groupId FROM groups WHERE `groups`.`id`+0 <= ?;
    

    说明:
    通过将+0 添加到列中,MySQL 会自动将该列视为整数并使用枚举索引而不是值。这是一个简单的技巧,可能会导致其他问题,但我到目前为止没有遇到任何问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-31
      • 2016-01-12
      • 2016-09-10
      • 1970-01-01
      • 2016-12-30
      • 1970-01-01
      • 1970-01-01
      • 2014-07-20
      相关资源
      最近更新 更多