【问题标题】:How to insert an Array to mysql without executing in a loop如何在不循环执行的情况下将数组插入mysql
【发布时间】:2019-11-29 02:52:00
【问题描述】:

我目前遇到了一个问题,我想通过 pdo 将带有准备好的语句的数组插入到我的数据库中。我从这里找到了一些代码,但目前它只在传递给该方法的数组 $files 中插入其中一个文件。

$amount = count($files);

for($i=0; $i<$amount; $i++){

    $dbArr=[
        'path'      => (string) dirname( $files[$i] ),
        'name'      => (string) basename( $files[$i] ),
        'size'      => (int) filesize($files[$i]),
        'mimeType'  => (string) mime_content_type( $files[$i] ),
    ];
}

foreach($dbArr as $k => $v ) {
    $prep[':'.$k] = $v;
}

new sql();

$q = sql::$db->prepare($str = "INSERT INTO filesSrc ( " . implode(', ',array_keys($dbArr)) . ") VALUES (" . implode(', ',array_keys($prep)) . ")");

$res = $q->execute($prep);

它可以工作,但只插入一个数组。解决方案可能很简单,我忽略了一些东西。

【问题讨论】:

    标签: php mysql arrays pdo insert


    【解决方案1】:
    $params = [
            'path'      => ':path',
            'name'      => ':name',
            'size'      => ':size',
            'mimeType'  => ':mineType',
        ];
    $sql    = "INSERT INTO filesSrc ( " . implode(',', array_keys($params)) . ") VALUES (" . implode(',', $params) . ")";
    $amount = count($files);
    $dbArrs = [];
    for($i=0; $i<$amount; $i++){
    
        $dbArrs[] = [
            'path'      => (string) dirname( $files[$i] ),
            'name'      => (string) basename( $files[$i] ),
            'size'      => (int) filesize($files[$i]),
            'mimeType'  => (string) mime_content_type( $files[$i] ),
        ];
    }
    
    
    
    new sql();
    #todo It is recommended to use 'try catch'
    $q = sql::$db->prepare($sql);
    foreach ($dbArrs as $dbArr) {
        foreach ($params as $key => $param) {
            $q->bindParam($param, $dbArr[$key]);
        }
        $q->execute();
    }
    

    【讨论】:

    • 您好,欢迎来到 StackOverflow。如果没有根本不同,请不要发布第二个答案。然后我建议把它打包成一个。为了您的信息,如果您获得更多信息或注意到任何应该更改的内容,您可以编辑您的答案(点击问题下方的编辑按钮 [左下])
    • 是否以正确的方式循环执行?我以为我最终会得到一个执行功能?在我用循环中的多个语句做这些事情之前,这就是我这次想要阻止的。
    • 因为没有看到整体代码,所以无法提供准确的功能。
    • 如果要插入大量数据,建议使用异步模式。
    【解决方案2】:

    除非您要插入数千行,否则我只会在事务中使用一条准备好的语句将它们一一插入。

    $q = sql::$db->prepare("
        INSERT INTO filesSrc (path, name, size, mimeType)
        VALUES (:path, :name, :size, :mimeType)
    ";
    
    sql::$db->beginTransaction();
    
    foreach ($files as $file) {
        $q->execute([
            'path'      => (string) dirname($file),
            'name'      => (string) basename($file),
            'size'      => (int) filesize($file),
            'mimeType'  => (string) mime_content_type($file),
        ]);
    }
    
    sql::$db->commit();
    

    如果你真的想执行批量插入(单多行插入),那么我会使用? 作为占位符:

    $values = [];
    $params = [];
    
    foreach ($files as $file) {
        $values[] = '(?,?,?,?)';
        $params[] = (string) dirname($file);
        $params[] = (string) basename($file);
        $params[] = (int) filesize($file);
        $params[] = (string) mime_content_type($file);
    }
    
    $values = implode(',', $values);
    
    $q = sql::$db->prepare("
        INSERT INTO filesSrc (path, name, size, mimeType)
        VALUES ($values)
    ";
    
    $res = $q->execute($params);
    

    要使用命名参数而不是 ?,请将 for 循环更改为:

    foreach ($files as $k => $file) {
        $values[] = "(:path_{$k}, :name_{$k}, :size_{$k}, :mimeType_{$k})";
        $params['path_{$k}'] = (string) dirname($file);
        $params['name_{$k}'] = (string) basename($file);
        $params['size_{$k}'] = (int) filesize($file);
        $params['mimeType_{$k}'] = (string) mime_content_type($file);
    }
    

    【讨论】:

    • 什么函数给我一个正确的布尔返回的数据库成功? $q?或 sql::$db->commit()?
    • 你不是在异常模式下使用 PDO 吗?
    • 我正在使用这个参数 PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    • 那么失败的prepare(...)execute(..) 将引发异常,您不需要布尔值来检查错误。如果需要,请改用 try-catch 块。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-31
    相关资源
    最近更新 更多