Trying to make insert or update sql using the prepared statements from php's pdo. First I thought of using REPLACE INTO command,but it gives me an error because I have a foreign key on my index. Read that I must use INSERT...ON DUPLICATE KEY UPDATE syntax to make it working, but it's not clear for me how to do that with prepared statements. Any solution for this? Thanks.
The sql is :
$sql="REPLACE INTO fn_currencies(id,short,name,buy,sell,date) VALUES (:id,:short,:name,:buy,:sell,:update)";
UPD: I am making this query in Yii that uses personal wrapper over the PDO.
When I use unnamed parameters I get this type of error:
CDbCommand failed to execute the SQL statement: SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens. The SQL statement executed was: INSERT INTO `fn_currencies` (id,short,name,buy,sell,date) VALUES (?,?,?,?,?,?) ON DUPLICATE KEY UPDATE id=?,short=?,name=?,buy=?,sell=?,date=?
When I use the named parameters with differed names for Insert and Update as was mentioned..I get no errors and neither data is inserted in my DB.
Here is the schema for the DB:
CREATE TABLE IF NOT EXISTS `fn_currencies` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`short` varchar(4) NOT NULL,
`name` varchar(200) NOT NULL,
`buy` decimal(10,4) NOT NULL,
`sell` decimal(10,4) NOT NULL,
`date` date NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
--
ALTER TABLE `fn_currencies`
ADD CONSTRAINT `FK_fn_currencies` FOREIGN KEY (`id`) REFERENCES `fn_operations` (`currency_id`);
Thanks to DavaRandom, he pointed out an error in my code, but this should do the trick. Replace the named parameter with ? and use an array merge to make the SQL on the fly like this:
$sql="
insert INTO fn_currencies(id,short,name,buy,sell,date)
VALUES (?,?,?,?,?,?)
on duplicate key update currencies set
short=?, name=?, buy=?, sell=?, update=?";
$values=array("id"=>1, "short"=>36, "name"=>'Bazinga', "sell"=>3.67, "date"=>'2012-08-08');
$db->query($sql, array_merge(array_values($values),array_values($values)));
Apparently this will also work (See comments all over the page about yes/no/maybe) but the above will certainly work:
$sql="
insert INTO fn_currencies(id,short,name,buy,sell,date)
VALUES (:id,:short,:name,:buy,:sell,:update)
on duplicate key update currencies set
short=:short, name=:name, buy=:buy, sell=:Sell, update=:update";
Related
CREATE TABLE IF NOT EXISTS `$id` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`start` varchar(10) NOT NULL,
`end` varchar(10) NOT NULL,
`date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=45 ;
INSERT INTO `$id`(`start`, `end`) VALUES ('0','0')
I have been trying to figure out how I can bind these two Mysql(requests(?)) into one with no success. Basically I want it to work so when I create the table it should also add the values 0 and 0 to "start" and "end" rows. But I still want the "Create table if not exists" to be in effect for the INSERT INTO. So if the table exist don't INSERT either.
You could do that with following single statement:
CREATE TABLE IF NOT EXISTS `$id` (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
`start` VARCHAR(10) NOT NULL,
`end` VARCHAR(10) NOT NULL,
`date` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB
SELECT '0' AS `start`, '0' AS `end`;
You use the CREATE TABLE ... SELECT syntax with selecting not from a table, but constant values and get the autoincrement value and the current_timestamp by default.
as of MySQL 5.5.6 or newer, see following excerpt from the manual, CREATE TABLE ... SELECT:
As of MySQL 5.5.6, handling of CREATE TABLE IF NOT EXISTS ... SELECT
statements was changed for the case that the destination table already
exists. This change also involves a change in MySQL 5.1 beginning with
5.1.51.
Previously, for CREATE TABLE IF NOT EXISTS ... SELECT, MySQL produced
a warning that the table exists, but inserted the rows and wrote the
statement to the binary log anyway. By contrast, CREATE TABLE ...
SELECT (without IF NOT EXISTS) failed with an error, but MySQL
inserted no rows and did not write the statement to the binary log.
MySQL now handles both statements the same way when the destination
table exists, in that neither statement inserts rows or is written to
the binary log. The difference between them is that MySQL produces a
warning when IF NOT EXISTS is present and an error when it is not.
This change means that, for the preceding example, the CREATE TABLE IF
NOT EXISTS ... SELECT statement inserts nothing into the destination
table as of MySQL 5.5.6.
Hi i am importing a csv through a script
the table structure is as below
`contact_id` int(11) NOT NULL auto_increment,
`contact_first` varchar(255) character set latin1 default NULL,
`contact_last` varchar(255) character set latin1 default NULL,
`contact_email` varchar(255) character set latin1 default NULL,
PRIMARY KEY (`contact_id`)
and the data in csv is like this
Jim,Smith,jim#tester.com
Joe,Tester,joe#tester.com
and the query i am using for insert is as below
mysql_query("INSERT IGNORE INTO contacts (contact_first, contact_last, contact_email) VALUES
(
'".addslashes($data[0])."',
'".addslashes($data[1])."',
'".addslashes($data[2])."'
)
");
i have made use of ignore function in the query but it doesnot work and it keeep on onserting the same value
The IGNORE keyword will only have your desired impact on duplicate rows.
A row will only be recognized as a duplicate if you have a primary key or unique key on the appropriate columns.
You haven't really explained exactly what the issue is, but I suspect you might want to create a unique key on the contact_email column to prevent duplicates from being inserted.
I would also suggest at a minimum using mysql_escape_string instead of addslashes to ensure the strings are encoded correctly.
There will likely be comments on the fact that the mysql_* functions are deprecated so you should look into PDO or mysqli_* functions.
If you use the IGNORE keyword, errors that occur while executing the INSERT statement are treated as warnings instead
Refer DOCS
The use of IGNORE is :
If you use the IGNORE keyword, errors that occur while executing the INSERT statement are treated as warnings instead. For example, without IGNORE, a row that duplicates an existing UNIQUE index or PRIMARY KEY value in the table causes a duplicate-key error and the statement is aborted. With IGNORE, the row still is not inserted, but no error is issued.
in your case you are inserting three values which are same but as the ID is auto incremental which will insert new record with same values which is obvious.
If you want to prevent it from inserting in to the database you have to add unique index to one of the other column
hope it will help!
I have a simple table
CREATE TABLE `keys` (
`IDkey` int NOT NULL auto_increment,
`username` varchar(50) NOT NULL,
PRIMARY KEY (`IDkey`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
and give out incrementing integer keys 'IDkey' to users as they call in with my webapp. I also store their username in the table.
I have two questions I'm stuck on.
First question: at the moment I am doing the following to give out the key, is there a way to combine this into one query?
INSERT INTO keys VALUES (NULL, '$username');
SELECT IDkey FROM keys WHERE username='$username';
Second Question: the key expires so the same user may return for a new key but this causes a problem because their username is already in the database. Is there a way to write my SELECT query so it returns the most recent record by that user?
If you're using PDO, check out PDO::lastInsertId().
If you're using mysqli, check out mysqli::$insert_id.
If you're using mysql, upgrade your code to use PDO or mysqli. ;-) (But seriously, you can do this with mysql_insert_id()).
Immediately call this function mysql_insert_id() after you insert this record. It will give you the id of last inserted record.
Using PHP I'm inserting a record in a MySQL database. If the record is new I get the insert_id but if it already exists I can't get the id using a single query.
Both of the following queries allow me to add the record or skip if it already exists:
INSERT INTO `emails` (`email`) VALUE ('abc#example.com') ON DUPLICATE KEY UPDATE `id`=`id`
INSERT IGNORE INTO `emails` (`email`) VALUE ('abc#example.com')
What is the right way to get the right result in both cases?
EDIT: Here's my table syntax:
CREATE TABLE `emails` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`email` varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
UNIQUE KEY `email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
I suspect that it's the value of LAST_INSERT_ID that ends up in insert_id.
Quote from the MySQL manual;
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;
Source: http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html
I'm developing a PHP web app using a MySQL database.
I'm wondering what is the best way to find out what primary key (or any other autoincrement field) did a row receive after insertion.
Something that returns the full row as a result is also pretty good, since I also wanted to know about default values assigned to fields I didn't explicitly set.
All help is appreciated.
-- edit
So, I'm using an in-house framework that abstracts away the actual database functions, so I can't use the connection-specific "mysql_last_insert_id", and the "select last_insert_id" query, AFAIK, would be affected by other database connections, especially considering that the framework I'm using opens new connections for every query.
Guess this is a framework problem and you can't help me. If INSERT INTO had a "return inserted rows" mode, though, that would be nice.
MySQL provides a convenient way to answer this exact question:
mysql> SELECT LAST_INSERT_ID()
The mysql_* functions come with a wrapper for that: check mysql_insert_id
The mysql driver for PDO gives the same:
$pdo->exec('insert into ...');
$lastId = $pdo->lastInsertId();
Try this
MySQL CODE:
CREATE TABLE IF NOT EXISTS `mytable` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`member` int(11) NOT NULL,
`update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`created` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`id`),
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
SHOW:
AUTO_INCREMENT
MySQL Insert:
INSERT INTO mytable (`id`,`name`,`update`,`created`) values (NULL,'TEST',NOW(),NOW());
OR
INSERT INTO mytable (`name`,`update`,`created`) values ('TEST',NOW(),NOW());
OR
INSERT INTO mytable (`name`,`created`) values ('TEST',NOW());
PHP MySQL Code:
<?php
$foo = 'test';
mysql_query("INSERT INTO mytable (`name`,`created`) values ('".mysql_real_escape_string( $foo )."',NOW())");
// GET LAST ID
$id = mysql_insert_id();
?>
In PHP use MYSQL_REAL_ESCAPE_STRING
mysql_real_escape_string( string )
See this doc mysql_real_escape_string
Bye!!
If you're using mysql_* functions, then you can simply use mysql_insert_id(). If you want the values of default rows, you'll have to select them using the key.