2014-10-27 88 views
0

有没有一种方法来使用PHP动态插入功能?多个INSERT INTO查询

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

我曾经想过一个开关块,东西就这个伪代码行:

但是此块仅与硬编码的情况下交易。我想知道是否有办法操纵查询,并设置为适应从文件中读取的值的数量并指定写入适当的表格?

编辑:我设法开发了我想要的动态系统,有可能追加我想要的字符串值然后运行字符串。我稍微改了一些代码(只有处理这个主题的部分在这里),所以如果复制和粘贴它不应该工作,但是我知道我是如何做到的。欢呼的答案。

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); 
     } 
} 
+0

什么是表格结构和你得到的值? – 2014-10-27 10:58:45

+0

您必须指定哪些“列”包含在特定值中。然后你可以用动态列和动态值填充查询。 – Adimeus 2014-10-27 10:59:23

+0

将会有几个表格,每个表格都有多个值。该表在被调用函数之前是已知的,我仍然没有编码,我只是在探索这些选项。 我想我明白你的意思@Adimeus。 – Comum 2014-10-27 11:04:40

回答

0

可能的解决方法。

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

它也使用一个类一次插入多行(在一个插入语句中插入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; 
     } 
    } 
} 

?> 

该类需要一个带查询方法的数据库类。您应该很容易将其更改为与您正在使用的连接相匹配。

+0

我会研究你的代码,并试着理解它的逻辑。主要是因为我的代码缺乏效率(如你所建议的),我需要提高传输速度。干杯。 – Comum 2014-10-27 13:23:05

0

这听起来像你想的各种INSERT语句中,可以自动识别从输入文件中提供的数据项(和数据项的可能的类型)的数量使用哪个表。

您的问题的答案:不,SQL不这样做。

从你的问题,你很好地创建一个客户端程序,这是特定于你的应用程序,将做你想做的。编写自己的程序是一种正确的方法:您可以在知道应用程序细节的情况下控制表选择逻辑和错误处理。

0

基于阵列的方法

而是附加了一些到外地的,使用基于阵列的方法:

<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' => '...', 
    ) 
) 

这使您可以执行插入onc的逻辑e,然后用一个循环来完成所有的字段。

的(伪)代码将是这样的:

$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 
     } 
    } 
} 
0
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); 
}