MySQL - Insert intro if exist update - php

I have unknown keys and values to import to database from CSV.
My code is
while($data = fgetcsv($handle,1000,",",'"'))
{
$data=array_map('addslashes',$data); // apply addslashes() to all values
$data=array_combine($csv_fields,$data); // csv fields assoc (key=>value)
$data=array_intersect_key($data,$tbl_fields); // discard redundant
$tbl_fields_str=implode("`,`",array_keys($data));
$tbl_vals_str=implode("','",array_values($data));
$q="INSERT INTO `cmid` (`cmid`,`$tbl_fields_str`) VALUES ('$cmidtrenutni','$tbl_vals_str') ON DUPLICATE KEY UPDATE (`$tbl_fields_str`) VALUES ('$tbl_vals_str')";
$conn->query($q);
}
I need to insert and if exist, update.
I try this code above but doesnt work.
I find something like http://dev.mysql.com/doc/refman/5.5/en/insert-on-duplicate.html
But this doesnt help in my way cause my table doesnt have defined fields. Keys and values are different on every input.
Any solution how to do this?

This is your query:
INSERT INTO `cmid` (`cmid`, `$tbl_fields_str`)
VALUES ('$cmidtrenutni', '$tbl_vals_str')
ON DUPLICATE KEY UPDATE (`$tbl_fields_str`) VALUES ('$tbl_vals_str');
The problem is the UPDATE part. You need to split the values so it looks like:
INSERT INTO `cmid` (`cmid`, `$tbl_fields_str`)
VALUES ('$cmidtrenutni', '$tbl_vals_str')
ON DUPLICATE KEY UPDATE
col1 = newcol1val,
col2 = newcol2val,
. . .
The short-hand that you are using is not valid syntax.

To import from a csv file, take a look at the LOAD DATA INFILE statement or the mysqlimport utility.

Try this one:
$q="INSERT INTO `cmid` (`cmid`,`$tbl_fields_str`) VALUES ('$cmidtrenutni','$tbl_vals_str') ON DUPLICATE KEY UPDATE cmid=cmid";
But I prefer using INSERT IGNORE for your problem:
$q="INSERT IGNORE INTO `cmid` (`cmid`,`$tbl_fields_str`) VALUES ('$cmidtrenutni','$tbl_vals_str')";

You cannot have "unknown" columns in mysql DB. if you want to store pairs of key-value in a mysql table, you should have a table with two columns : one would be named "key" and the other one "value". Add an extra column "cmid" to group your pairs.
This table should have a primary index on "cmid" and "key" columns.
Then you should insert values with a query like:
$sqlVals = "";
foreach ($data as $key => $val) {
$sqlVals .= "($cmidtrenutni, $key, $val),";
}
$sqlVals = substr($sqlVals, 0, -1); //remove last comma.
$query = "REPLACE INTO `myTable` (`cmid`, `key`,`value`) VALUES $sqlVals";

Related

insert multiple row in sql database with php

I want to insert multiple row in sql with php, after checking few conditions.
The condition is, if 'cat' and 'preview' is not null then row one will be submitted and if 'cat','preview','cat2','preview2' is not null then two row will submitted with first row's value 'cat' and'preview and 2nd row's value 'cat2' and 'preview2'.
i tried these code, but i see - Undefined variable: sql
whats wrong with my condition?
else if(isset($cat)and ($cat!=="") and isset($preview)and ($preview=="") and
(isset($cat2))and ($cat2!=="") and (isset($preview2))and ($preview2!==""))
{
$sql = "INSERT INTO files (cat, preview, file, art) VALUES
('".$cat."','".$preview."','".$file."','".$art."')
('".$cat2."','".$preview2."','".$file2."','".$art2."')";
}
your code just had query mistake that you wanted to insert two row in just one insert command.use this code that seperates the insert commands :
else if(!empty($cat) and !empty($preview) and
!empty($cat2) and !empty($preview2))
{
$sql = "INSERT INTO files (cat, preview, file, art) VALUES
('".$cat."','".$preview."','".$file."','".$art."');";
$sql .= " INSERT INTO files (cat, preview, file, art) VALUES ('".$cat2."','".$preview2."','".$file2."','".$art2."');";
}
I personally think that the logic you have with your conditions may need rethinking. For instance, if you save your values into arrays, you can automate this process:
// Save first values
$sqlArgs[] = array($cat,$preview,$file,$art);
// Save second values
$sqlArgs[] = array($cat2,$preview2,$file2,$art2);
// Loop through each row.
foreach($sqlArgs as $key => $array) {
// If the `cat` or the `preview` empty, skip
if(!empty(trim($array[0])) && !empty(trim($array[1])))
$sql[] = "'".implode("','",$array)."'";
}
// If the sql has rows continue
if(!empty($sql)) {
// Build the statement rows with implode() of values.
// This assumes these are not user-input values or that you have
// thoroughly sanitized the values.
$statement = "INSERT INTO `files` (`cat`,`preview`,`file`,`art`) VALUES (".implode("),(",$sql).")";
// Preview statement
print_r($statement);
}
This approach will take care of 0,1, or 2 inserts (or more if necessary) based on the two keys cat & preview being filled.
Insert query with ; is not one query...
For example
Insert into mytable (a,b,c) values (1,2,3);
Insert into mytable (a,b,c) values (4,5,6);
Insert into mytable (a,b,c) values (7,8,9);
is not one query, this is 3 insert queries.
That is mean when insert values (4,5,6) have error, values (1,2,3) query is successed....
We want if one row failed, all insert query fail.
Therefore, we don't write insert query with ;
Example query:
Insert into mytable values(1, 2, 3), (4, 5, 6), (7, 8, 9);

Using On Duplicate Key Update with an array

I'm relatively new to MYSQL and am having trouble combining idea I have read about. I have a form generated from a query. I want to be able to insert or update depending on whether there is currently a matching row. I have the following code which works for inserting but I;m struggling with the On DUPLICATE UPDATE part I keep getting a message saying there is an error in my syntax or unexpeted ON depending on how I put the ' .
require_once("connect_db.php");
$row_data = array();
foreach($_POST['attendancerecordid'] as $row=>$attendancerecordid) {
$attendancerecordid=mysqli_real_escape_string($dbc,$attendancerecordid);
$employeeid=mysqli_real_escape_string($dbc,($_POST['employeeid'][$row]));
$linemanagerid=mysqli_real_escape_string($dbc,($_POST['linemanagerid'][$row]));
$abscencecode=mysqli_real_escape_string($dbc,($_POST['abscencecode'][$row]));
$date=mysqli_real_escape_string($dbc,($_POST['date'][$row]));
$row_data[] = "('$attendancerecordid', '$employeeid', '$linemanagerid', '$abscencecode', '$date')";
}
if (!empty($row_data)) {
$sql = 'INSERT INTO attendance (attendancerecord, employeeid, linemanagerid, abscencecode, date) VALUES '.implode(',', $row_data)
ON DUPLICATE KEY UPDATE abscencecode = $row_data[abscencecode];
echo $sql;
$result = mysqli_query ($dbc, $sql) or die(mysqli_error ($dbc));
}
The various echo statements are showing that the correct data is coming through and my select statement was as expected before I added in the ON DUPLICATE statement.
You need to fix the way the sql statement is constructed via string concatenation. When you create an sql statement, echo it and run it in your favourite mysql manager app for testing.
$sql = 'INSERT INTO attendance (attendancerecord, employeeid, linemanagerid, abscencecode, date) VALUES ('.implode(',', $row_data).') ON DUPLICATE KEY UPDATE abscencecode = 1'; //1 is a fixed value yiu choose
UPDATE: Just noticed that your $row_data array does not have named keys, it just contains the entire new rows values as string. Since you do bulk insert (multiple rows inserted in 1 statement), you have to provide a single absencecode in the on duplicate key clause, or you have to execute each row in a separate insert to get the absence code for each row in a loop.

MySQL stops running queries after if statement

I've been stuck on this for a few hours now ...
Here's my code:
$SQLQuery1 = $db_info->prepare("SELECT COUNT(ID) FROM menusize WHERE typesize=:typesize");
$SQLQuery1->bindValue(':typesize',$_POST['typesize'],PDO::PARAM_STR);
$SQLQuery1->execute();
if($SQLQuery1->fetchColumn() > 0) {
$SQLQuery2 = $db_info->prepare("INSERT INTO menucatagorysize (menucatagory_ID,menusize_ID) VALUES (:catagoryid,(SELECT ID FROM menusize WHERE typesize=:typesize))");
$SQLQuery2->bindValue(':typesize',$_POST['typesize'],PDO::PARAM_STR);
$SQLQuery2->bindValue(':catagoryid',$_POST['catagoryid'],PDO::PARAM_STR);
$SQLQuery2->execute();
} else {
$SQLQuery2 = $db_info->prepare("INSERT INTO menusize (typesize) VALUES (:typesize);
SET #menusizeid=LAST_INSERT_ID();
INSERT INTO menucatagorysize (menusize_ID,menucatagory_ID) VALUES (#menusizeid,:catagoryid)");
$SQLQuery2->bindValue(':typesize',$_POST['typesize'],PDO::PARAM_STR);
$SQLQuery2->bindValue(':catagoryid',$_POST['catagoryid'],PDO::PARAM_STR);
$SQLQuery2->execute();
}
$SQLQuery3 = $db_info->prepare("SELECT DISTINCT(menuitem_ID) FROM menuprice WHERE menucatagory_ID=:catagoryid");
$SQLQuery3->bindValue(':catagoryid',$_POST['catagoryid'],PDO::PARAM_STR);
$SQLQuery3->execute();
$rows = $SQLQuery3->fetchAll(PDO::FETCH_ASSOC);
So, it will run through the if statement fine, running $SQLQuery1 and $SQLQuery2 (Which ever one is required) without any problems, errors or warnings. But, if it runs the else { part of the code, it will not run $SQLQuery3. Any thoughts?
Thanks :D
EDIT: Got it to work by doing $SQLQuery2=NULL in the else statement ... Sucks that I still cant figure out why it wouldnt work the original way.
It appears that you're trying to enforce a uniqueness constraint over the typesize column of your menusize table from within your application code. However, the database can do this for you—which will make your subsequent operations much simpler:
ALTER TABLE menusize ADD UNIQUE (typesize)
Now, one can simply attempt to insert the posted value into the table and the database will prevent duplicates arising. Furthermore, as documented under INSERT ... ON DUPLICATE KEY UPDATE Syntax:
If a table contains an AUTO_INCREMENT column and INSERT ... ON DUPLICATE KEY UPDATE inserts or updates a row, the LAST_INSERT_ID() function returns the AUTO_INCREMENT value. Exception: For updates, LAST_INSERT_ID() is not meaningful prior to MySQL 5.1.12. However, you can work around this by using LAST_INSERT_ID(expr). Suppose that id is the AUTO_INCREMENT column. To make LAST_INSERT_ID() meaningful for updates, insert rows as follows:
INSERT INTO table (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), c=3;
Therefore, you can do:
$db_info->prepare('
INSERT INTO menusize (typesize) VALUES (:typesize)
ON DUPLICATE KEY UPDATE typesize=LAST_INSERT_ID(typesize)
')->execute(array(
':typesize' => $_POST['typesize']
));
$db_info->prepare('
INSERT INTO menucatagorysize
(menusize_ID, menucatagory_ID)
VALUES
(LAST_INSERT_ID(), :catagoryid)
')->execute(array(
':catagoryid' => $_POST['catagoryid']
));
$stmt = $db_info->prepare('
SELECT DISTINCT menuitem_ID
FROM menuprice
WHERE menucatagory_ID = :catagoryid
');
$stmt->execute(array(
':catagoryid' => $_POST['catagoryid']
));
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
// etc.
}
(As an aside, the English word is spelled cat*e*gory, not cat*a*gory.)

INSERT into Table On Columns That Exist

Suppose I have a very large array of information for a user:
$user=array(
"name"=>"john",
"ip"=>"xx.xx.xx.xx",
"email"=>"john#something.com",
//lots more values
)
Let's also suppose that this information needs to go into more than one table. For instance a username needs to go table users, address needs to go into a details table, etc.
Now, I use a certain self-made function to insert into my tables that matches array keys to column names and array values to the values being inputted. Something similar to this:
function insert_sql($table, arr $values){
GLOBAL $dbc;
$sql="INSERT INTO `$table` (".implode(array_keys($values), ", ").") VALUES (".implode(array_values($values), ", ").")";
$dbc->prepare($sql)->execute();
return $dbc->lastInsertId();
}
//I don't actually use this function, just trying to show you what is being accomplished.
The problem is that my function uses all the keys and all the values, so when I just need certain parts of the array put into multiple tables, it doesn't work.
The question is:
How do I make an INSERT statement ignore a column if it doesn't exist? So if I insert name,email,address, into table users, but this table doesn't have an address column, I need it to insert the row with the name and email but simply ignore the fact that the address column is not there.
EDIT: The other option is to make an array with the columns of a table and use it to filter the values array. Although I am not really sure how to set this up.
Find given table column names:
SELECT
column_name
FROM
information_schema.columns
WHERE
table_name = 'tablename'
And then just whitelist your keys in $values array
Example:
function insert_sql($table, array $values){
global $connection;
$query = "SELECT column_name FROM information_schema.columns WHERE table_name = :tablename";
/* #var $stmt PDOStatement */
$stmt = $connection->prepare($query);
$stmt->execute(array(
'tablename' => $table
));
$columns = array_flip($stmt->fetchAll(PDO::FETCH_COLUMN, 0));
$values = array_intersect_key($values, $columns);
var_dump($values);
}
How do I make an INSERT statement ignore a column if it doesn't exist?
So if I insert name,email,address, into table users, but this table
doesn't have an address column, I need it to insert the row with the
name and email but simply ignore the fact that the address column is
not there.
You can't
Instead you should map your data to the appropriate tables with separate inserts.

Check if exists, if so, update by 1++, if not insert

Hey guys quick question, I currently have an insert statement
$query= "INSERT into new_mail VALUES ('$to1', '0')"; where fields are username, and message_number
Currently what I would do to check if the entry exists, is do a select query then check the number of rows with mysql_num_rows (php). If rows==1 then I get the current message_number and set it equal to
$row['message_number']+1.
Then I update that entry with another query.
Is there an easier way to do all this in just mysql with just one query (check if exists, if not insert, if so update message_number, increase by 1)?
Depending on how your table is structured, you may be able to use the ON DUPLICATE KEY UPDATE (link to the MySQL manual) feature of INSERT:
INSERT into new_mail VALUES ('$to1', '0') ON DUPLICATE KEY UPDATE message_number=message_number+1
Use INSERT...ON DUPLICATE KEY UPDATE. The MySQL manual has an example which does almost exactly what you need:
INSERT INTO table (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE c=c+1;
To make this work you need to add a UNIQUE index on the column that you use to check for duplicates. There is one important warning though:
In general, you should try to avoid using an ON DUPLICATE KEY clause on tables with multiple unique indexes.
Got a little confused by your question and your table structures but I think you want something like this.
INSERT INTO new_mail (username, message_number)
VALUES ($username, $message_number)
ON DUPLICATE KEY UPDATE message_number=message_number + 1;
This is presuming username is your primary key (more likely something like userid). Hope this helps.
EDIT: The ON DUPLICATE KEY UPDATE answers are better, but you could do this (eludes the select query):
Assuming you're using the mysqli extenson:
$db = //Some construction of mysqli object;
$sql = 'UPDATE tablename SET RowValue = RowValue + 1 WHERE message_number = ?';
$updateStatement = $db->prepare($sql);
$updateStatement->bind_param('i', $message_number);
$message_number = //Set message number;
$updateStatement->execute();
if ($updateStatement->affectedRows == 0) {
$sql = 'INSERT INTO tablename (RowValue, message_number) VALUES (?, ?)';
$insertStatement = $db->prepare($sql);
$insertStatement->bind_param('ii', $rowValue, $messageNumber);
$rowValue = something;
$messageNumber = something;
$insertStatement->execute();
}

Categories