3

我一直在尝试在drupal中运行一个查询,如果它们已经存在则更新条目,如果不存在则插入一个新条目。代码现在看起来像这样:

db_query("IF EXISTS (SELECT %d FROM {uc_posten_packages.pid})
UPDATE {uc_posten_packages} SET title = '%s', label = '%s', cost = '%d', length = '%d', width ='%d', height = '%d', weight = '%d'  WHERE pid = %d
ELSE
INSERT INTO {uc_posten_packages} VALUES ('%d', '%s', '%s', '%d', '%d', '%d', '%d', '%d')",$id, $title, $label, $rate, $length, $width, $height, $weight, $id, $id, $title, $label, $rate, $length, $width, $height, $weight);

我不明白为什么该查询会引发错误。错误中的所有数字都是正确的

...near 'IF EXISTS (SELECT 1 FROM uc_posten_packages.pid) UPDATE uc_posten_packages ' at line 1 query:
IF EXISTS (SELECT 1 FROM uc_posten_packages.pid) UPDATE uc_posten_packages SET title = 'vfbv', label = 'bbv', cost = '22', length = '232', width ='22', height = '22', weight = '22' WHERE pid = 1 ELSE INSERT INTO uc_posten_packages VALUES ('1', 'vfbv', 'bbv', '22', '232', '22', '22', '22')

这个查询是否应该工作和/或在drupal中是否有更好的方法来处理这个问题?

4

4 回答 4

6

您正在寻找的是亲切地称为“upsert”(更新否则插入),并且有一个drupal函数就是这样:db_merge。在这里写得很好:http: //drupal.org/node/310085

drupal_write_record() 不会自动执行“upsert”。它总是根据您传入的内容进行插入或更新,但不能同时进行。

于 2013-04-09T02:49:11.813 回答
4

[2013 年 1 月更新]

这个答案指的是比当前稳定版本更旧的 Drupal 版本。请通过添加这样的更新部分来编辑此答案,其中包含更多最新信息,因为我不再使用 Drupal 或跟上其 API 更改。

-森佩罗斯

[/2013 年 1 月更新]

您有几个选项,即drupal_write_record运行示例查询和测试结果。这不应该像您的问题那样在单个 SQL 查询中完成。

drupal_write_record(首选方法)

该函数drupal_write_record允许您指定要处理的表和包含该表的每个列/字段的数据的对象(或关联数组)。如果您已经拥有要更新的行的主键,那么您将其作为第三个参数包含在函数中,并且drupal_write_record将自动使用 SQLUPDATE命令。否则,它默认为INSERT. 例如:

drupal_write_record('uc_posten_packages', array('title'  => "Foobar",
                                      'label'  => "foobar",
                                      'cost'   => 10,
                                      'length' => 100,));

这将INSERT是一个包含该信息的新记录。如果您包含第三个参数array($pid)where$pid是充当表的主键的字段的名称,则它将执行更新。

此功能仅在您正在处理的表是使用定义的情况下才有效hook_schema,这对于任何正确开发的具有数据库表的 Drupal 模块都应该是正确的。由于这个函数使用模式来确保它正确地写入数据库,你应该尽可能使用这个函数(或者当不存在其他更具体的函数时,例如node_save节点对象)。

测试查询

您可以使用db_result(db_query("SELECT...")). 如果没有找到结果,它将返回一个空字符串,在 PHP 中它的计算结果为 false,因此您的代码可能如下所示:

if (db_result(db_query("SELECT * FROM {uc_posten_packages} WHERE pid = %d", $pid))) {
  // UPDATE
} else {
  // INSERT
}
于 2011-04-28T23:02:25.480 回答
1

根据drupal_write_record操作是一个UPDATE或一个INSERT你需要在提交事务之前知道记录是否存在。这不是 drupal_write_record() 所做的。这个函数只是检查它的参数并相应地发出更新或插入。因此,实际上没有办法判断该函数是执行 anINSERT还是 an UPDATE

解决方案是使用db_merge()查询,它是一个相对较新的 SQL ANSI 标准,可以完全满足我的需要(在 MySQL 的情况下,它是在原子事务中完成的)。

$return_value = db_merge('mytable')
            ->key(array('id' => $key))
            ->fields($fields)
            ->updateFields(array(
                'updatedon' => $now,
            ))
            ->execute();

返回值是一个整数,对于插入返回 1,对于更新返回 2。

于 2016-02-26T20:25:57.247 回答
0

这是替换语法的一个愚蠢示例。

mysql> create table test (
    -> id int,
    -> a int,
    -> b int,
    -> unique (id)
    -> ) engine = myisam;
Query OK, 0 rows affected (0.01 sec)

mysql> replace into test (id,a,b) values (1,4,2);
Query OK, 1 row affected (0.00 sec)

mysql> replace into test (id,a,b) values (2,10,3);
Query OK, 1 row affected (0.00 sec)

mysql> select * from test;
+------+------+------+
| id   | a    | b    |
+------+------+------+
|    1 |    4 |    2 |
|    2 |   10 |    3 |
+------+------+------+
2 rows in set (0.00 sec)

mysql> replace into test (id,a,b) values (1,5,5);
Query OK, 2 rows affected (0.00 sec)

mysql> select * from test;
+------+------+------+
| id   | a    | b    |
+------+------+------+
|    1 |    5 |    5 |
|    2 |   10 |    3 |
+------+------+------+
2 rows in set (0.00 sec)

希望它可以帮助你。

于 2011-04-28T22:18:17.577 回答