多个INSERT INTO查询


Multiple INSERT INTO query

有没有一种方法可以使用PHP实现动态插入函数?

我有一个函数,它处理几个文件,这些文件遵循相同的结构,但并不总是具有相同数量的值。例如,如果一个文件有10个值,它将写入某个表,如果它有3个值,则它将写入另一个表。

我想到了一个开关块,这个伪代码行上的东西:

function($table)
{
     $n_values = (number of values read from the file);
     switch($n_values)
     {
          case 1: $query = "INSERT INTO ".$table." VALUES('')";
                  break;
          case 2: $query = "INSERT INTO ".$table." VALUES('', '')";
                  break;
          (...)
     }
     $query->run();
}

然而,这个块只处理硬编码的情况。我想知道是否有一种方法可以操作查询,并将其设置为适应从文件中读取的值的数量,并指定写入正确的表?

编辑:我成功地开发了我想要的动态系统,可以将我想要的值附加到字符串中,然后运行该字符串。我对代码做了一点改动(这里只列出了处理这个主题的部分),所以如果复制粘贴的话,它不应该起作用,但我已经知道我是怎么做的了。为答案欢呼。

 function func($table)
 {
       open_file($file_name);
       //while (!$file_name->eof())
       {
            $line = explode(" ", trim($file->fgets()));
            $query = "INSERT INTO `".$table."` VALUES ('' "; //1st value is an a.i. id 
            for($i = 0 ; $i < get_num_values($file_name)); $i++)
            {
                $query = $query.', ' .$line[($i)]. '';
            }
            $query = $query . ')';
            $stmt = $con->query($query);
        }
 }

可能的解决方案。

这使用一个数组来存储每个列数的表名。

它还使用一个类一次插入多行(在一个insert语句中插入250行比单独插入250行快得多)。

它在表列表中循环,并为每个表创建一个新实例。

然后它读取文件。对于每一行,它调用具有该列数的文件的对象的make_row方法。当有一定数量的行要插入时(默认情况下为255行,易于更改),对象的类将进行插入,当调用__DESTRUCT时也将进行插入。

一旦输入文件完成,它就会围绕表对象循环并取消设置所有对象(这会触发每个对象的__DESTRUCT,清除所有剩余插入)。

<?php
$table_names = array(1=>'Table1Col', 2=>'Table2Col', 3=>'Table3Col', 4=>'Table4Col', 5=>'Table5Col' );
$table_process = array();
foreach($table_names as $table_col_count=>$table_name)
{
    $table_process[$table_col_count] = new table_process($con, $table_name);
}
open_file($file_name);
while (!$file_name->eof())
{
    $line = explode(" ", trim($file->fgets()));
    $table_process[count($line)]->make_row($line);
}
foreach($table_process as $table_process_name)
{
    unset($table_process_name);
}
class table_process
{
    var $db;
    var $row_array = array();
    var $field_name_store = '';
    var $table_name = '';
    var $record_count = 0;
    var $update_clause = '';
    var $rows_to_process = 255;
    function __CONSTRUCT($db, $table_name, $update_clause = '')
    {
        $this->db = $db;
        $this->table_name = $table_name;
        $this->update_clause = $update_clause;
    }
    function __DESTRUCT()
    {
        if (count($this->row_array) > 0)
        {
            $this->process_rows();
        }
    }
    function field_names($in_field_names)
    {
        $this->field_name_store = "(`".implode("`,`", $in_field_names)."`)";
    }
    function record_count()
    {
        return count($this->record_count);
    }
    function make_row($in_row)
    {
        $ret = true;
        foreach($in_row AS &$in_field)
        {
            $in_field = (($in_field == null) ? "NULL" : "'".$this->db->escape($in_field)."'");
        }
        $this->record_count++;
        $this->row_array[] = "(".implode(",", $in_row).")";
        if (count($this->row_array) > $this->rows_to_process)
        {
            $ret =  $this->process_rows();
        }
        return $ret;
    }
    function process_rows()
    {
        $ret = true;
        $sql = "INSERT INTO ".$this->table_name." ".$this->field_name_store." VALUES ".implode(",", $this->row_array)." ".$this->update_clause;
        if (!$this->db->query($sql))
        {
            $ret = false;
        }
        $this->row_array = array();
        return $ret;
    }
    public function set_rows_to_process($rows_to_process)
    {
        if (is_numeric($rows_to_process) and intval($rows_to_process) > 0)
        {
            $this->rows_to_process = $rows_to_process;
        }
    }
}
?>

该类需要一个带有查询方法的数据库类。您应该很容易更改它以匹配您正在使用的连接。

听起来您想要各种INSERT语句,这些语句可以根据输入文件中显示的数据项的数量(可能还有数据项的类型)自动辨别要使用哪个表。

你的问题的答案是:不,SQL不会这么做。

从您的问题来看,您正在创建一个特定于您的应用程序的客户端程序,该程序将执行您想要的操作。编写自己的程序是正确的方法:您可以通过了解应用程序的详细信息来控制表选择逻辑和错误处理。

基于阵列的方法

使用基于数组的方法:

<form action="" method="POST">
    <b>Product 1</b><br
    <label>Product Id <input type="text" name="products[0][id]"></label>
    <br>
    <label>Product Type <input type="text" name="products[0][type]"></label>
    <br>            
    <b>Product 2</b><br>
    <label>Product Id <input type="text" name="products[1][id]"></label>
    <br>
    <label>Product Type <input type="text" name="products[1][type]"></label>
</form>

现在,如果您要将其提交给PHP并执行print_r($_POST['products']);,你会得到如下的东西:

array(
    0 => array(
        'id' => '...',
        'type' => '...',
    ),
    1 => array(
        'id' => '...',
        'type' => '...',
    )
)

这允许您执行一次插入的逻辑,然后使用循环执行所有字段。

(伪)代码如下:

$products = (isset($_POST['products']) && is_array($_POST['products'])) ? $_POST['products'] : array();
//Note that I've assumed the id column is an int, and the type column is a string.
//In real schema, I would expect type to also be an int, but I want to illustrate proper escaping.
//(There is more on this in a later section)
$query = "INSERT INTO products (id, type) VALUES (%d, '%s')";
foreach ($products as $product) {
    //Ensure that $product contains a valid entry, and if it does not, store errors somewhere
    if (valid entry) {
        $res = mysql_query(sprintf($query, (int) $product['id'], mysql_real_escape_string($product['type'])));
        if (!$res) {
            //Log an error about the query failing
        }
    }
}
function func($table)
{
    open_file($file_name); 
    $line = explode(" ", trim($file->fgets()));
    $values = "'','".implode("','", $line)."'";
    $query = "INSERT INTO `{$table}` values ({$values})";
    $stmt = $con->query($query);
}

或者,不要先爆炸后内爆,只需将文件内容中的"替换为",",然后在前面和后面再添加一个"即可。然而,如果每个空间都有内容,那么你的爆炸会造成问题。如果你的数据库不喜欢引用数字,你可能不得不修改为不引用数字。

function func($table)
{
    open_file($file_name); 
    $values = "'','".str_replace(' ', "','", trim($file->fgets()))."'".
    $query = "INSERT INTO `{$table}` values ({$values})";
    $stmt = $con->query($query);
}