WordPress $wpdb. 插入多条记录

34

有没有办法在WordPress中使用 $wpdb->insert$wpdb->query($wpdb->prepare) 来实现以下操作:

INSERT into TABLE (column1, column2, column3) 
VALUES
('value1', 'value2', 'value3'),
('otherval1', 'otherval2', 'otherval3'),
('anotherval1', 'anotherval2', 'anotherval3')
非常抱歉,我只能理解英文。

WordPress 文档中似乎没有针对这种情况的语法。 - djt
WordPress并不是为与数据库交互而构建的框架,因此像这样的函数并不存在。如果您不想自己编写代码,那么循环和使用插入操作可能是最好的选择。 - jeremyharris
此外,我刚才浏览了wpdb类并没有找到任何插入多行的方法,因此你将不得不使用上述两种方法之一来执行它。 - jeremyharris
好的,我想我弄明白了。下面是答案。 - djt
很酷,很高兴你解决了它。请确保接受答案,这样其他人就知道问题已经解决 :) - jeremyharris
6个回答

79

好的,我解决了!

为实际值和占位符设置数组。

$values = array();
$place_holders = array();

最初的查询:

$query = "INSERT INTO orders (order_id, product_id, quantity) VALUES ";

然后遍历你想要添加的值,并将它们插入到适当的数组中:

foreach ( $_POST as $key => $value ) {
     array_push( $values, $value, $order_id );
     $place_holders[] = "('%d', '%d')" /* In my case, i know they will always be integers */
}

然后在初始查询中添加以下内容:

$query .= implode( ', ', $place_holders );
$wpdb->query( $wpdb->prepare( "$query ", $values ) );

5
好的,如果你需要插入字符串,请使用'%s'。 - andrewthong
3
在查询字符串中,%d和%s都应该不带引号。 - malletjo
这里需要使用 $place_holders[] 吗? - Hamid Araghi

20
你也可以使用这种方式构建查询:
$values = array();

// We're preparing each DB item on it's own. Makes the code cleaner.
foreach ( $items as $key => $value ) {
    $values[] = $wpdb->prepare( "(%d,%d)", $key, $value );
}

$query = "INSERT INTO orders (order_id, product_id, quantity) VALUES ";
$query .= implode( ",\n", $values );

5
我遇到了这个问题,并决定通过使用被接受的答案来构建一个更改进的函数:

/**
 * A method for inserting multiple rows into the specified table
 * 
 *  Usage Example: 
 *
 *  $insert_arrays = array();
 *  foreach($assets as $asset) {
 *
 *  $insert_arrays[] = array(
 *  'type' => "multiple_row_insert",
 *  'status' => 1,
 *  'name'=>$asset,
 *  'added_date' => current_time( 'mysql' ),
 *  'last_update' => current_time( 'mysql' ));
 *
 *  }
 *
 *  wp_insert_rows($insert_arrays);
 *
 *
 * @param array $row_arrays
 * @param string $wp_table_name
 * @return false|int
 *
 * @author  Ugur Mirza ZEYREK
 * @source https://dev59.com/Rmct5IYBdhLWcg3wEJcm#12374838
 */

function wp_insert_rows($row_arrays = array(), $wp_table_name) {
    global $wpdb;
    $wp_table_name = esc_sql($wp_table_name);
    // Setup arrays for Actual Values, and Placeholders
    $values = array();
    $place_holders = array();
    $query = "";
    $query_columns = "";

    $query .= "INSERT INTO {$wp_table_name} (";

            foreach($row_arrays as $count => $row_array)
            {

                foreach($row_array as $key => $value) {

                    if($count == 0) {
                        if($query_columns) {
                        $query_columns .= ",".$key."";
                        } else {
                        $query_columns .= "".$key."";
                        }
                    }

                    $values[] =  $value;

                    if(is_numeric($value)) {
                        if(isset($place_holders[$count])) {
                        $place_holders[$count] .= ", '%d'";
                        } else {
                        $place_holders[$count] .= "( '%d'";
                        }
                    } else {
                        if(isset($place_holders[$count])) {
                        $place_holders[$count] .= ", '%s'";
                        } else {
                        $place_holders[$count] .= "( '%s'";
                        }
                    }
                }
                        // mind closing the GAP
                        $place_holders[$count] .= ")";
            }

    $query .= " $query_columns ) VALUES ";

    $query .= implode(', ', $place_holders);

    if($wpdb->query($wpdb->prepare($query, $values))){
        return true;
    } else {
        return false;
    }

}

Source: https://github.com/mirzazeyrek/wp-multiple-insert


1
请注意,如果$row_arrays参数是一个关联数组,那么这将失败,因为if($count == 0)假定它是从0开始编号的数字。依赖未记录的假设并不是很好。最好使用不同的方法来区分第一行。 - Bence Szalai
感谢您的评论@Grapestain。在docblock中有解释,并且在github存储库中有其他示例。您想举个例子说明什么样的情况会导致该方法失败吗? - mirza
这个会失败: wp_insert_rows([ 'row1' => ['prop1', 'prop2'], 'row2' => ['propA', 'propB'] ] , 'my_table') 或者这个也会失败: wp_insert_rows([ 1 => ['prop1', 'prop2'], 2 => ['propA', 'propB'] ] , 'my_table') 而这个会成功: wp_insert_rows([ ['prop1', 'prop2'], ['propA', 'propB'] ] , 'my_table')这不是什么大问题,我只是对 $count == 0 的条件感到惊讶,因为它没有说明输入数组不能是关联数组(即不能使用自定义键)。我永远不会这样做,因为这意味着函数依赖于一种假设,而这种假设并没有得到强制执行。 - Bence Szalai

4
除了使用$wpdb插入多行数据外,如果您需要更新现有行,则以下代码片段应该很有帮助。这是上面@philipp提供的更新片段。
$values = array();

// We're preparing each DB item on it's own. Makes the code cleaner.
foreach ( $items as $key => $value ) {
    $values[] = $wpdb->prepare( "(%d,%d)", $key, $value );
}

$values = implode( ",\n", $values );
$query = "INSERT INTO orders (order_id, product_id, quantity) VALUES {$values} ON DUPLICATE KEY UPDATE `quantity` = VALUES(quantity)";

2
还没有测试过这个解决方案,但是我因为使用了ON DUPLICATE KEY UPDATE而给予+1的评价。 - HPWD
1
@HPWD 我有了。它运行良好。你也可以使用array_map来代替循环。(我不知道它是否是MySQL特定的,但请注意VALUES()语法引用将来的新值在MySQL 8.0.20中已废弃,但是在8.0.19中可以使用别名。) - Jake

-5

虽然有点晚了,但你也可以这样做。

    global $wpdb;
    $table_name = $wpdb->prefix . 'your_table';

    foreach ($your_array as $key => $value) {
          $result = $wpdb->insert( 
            $table_name, 
            array( 
              'colname_1' => $value[0], 
              'colname_2' => $value[1], 
              'colname_3' => $value[2], 
            ) 
          );
        }
  if (!$result) {
    print 'There was a error';
  }

3
这将执行多次单行的INSERT操作,而不是一次插入多行数据。同时,只会检测到最后一个插入操作中存在的错误。 - Bruno Ferreira

-7

虽然不太好看,但如果你知道你在做什么:

require_once('wp-load.php');
mysql_connect(DB_HOST, DB_USER, DB_PASSWORD);  
@mysql_select_db(DB_NAME) or die();
mysql_query("INSERT into TABLE ('column1', 'column2', 'column3') VALUES 
                               ('value1', 'value2', 'value3'), 
                               ('otherval1', 'otherval2', 'otherval3'),
                               ('anotherval1', 'anotherval2', 'anotherval3)");

9
这个解决方案很糟糕。请不要再使用古老的 mysql_ 函数,它们即将被弃用。 - kapa
5
我建议停止使用 or die(),这是处理错误的可怕方式。 - Diego

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接