I've used INSERT INTO hundreds of times, but it has been a while and I have been driving myself crazy on this one:
//Database Connection
$movieID = 41154;
$userID = 15;
$vote = 'yes';
$postVote = mysql_query("INSERT INTO votes (movieID, userID, yesNo, $vote) VALUES ('$movieID', '$userID', 1, 1)");
I'm able to successfully connect to the database and get data from the votes table, but for some reason, I'm having trouble using INSERT INTO.
The following columns exist in the vote table: movieID, userID, yesNo, and yes.
Any thoughts on what I can do differently? I must be overlooking something very obvious.
Using ... or die(mysql_error(), as Marc B pointed out, lead me to my problem. This displayed the error that I couldn't set duplicate keys...I forgot to auto increment the primary key for the votes table. Thus it kept trying to create a voteID of 1 each time I tried to INSERT INTO votes.
$postVote = mysql_query(...) or die(mysql_error());
This solved my challenge. However, Tim G points out that using PDO is a much better approach than mysql_query(). With a little bit of reading, Tim G is probably right about PDO. Based on PHPEveryday's Tutorial, I could rewrite my Insert Statement as such:
// database connection
$conn = new PDO("mysql:host=$dbhost;dbname=$dbname",$dbuser,$dbpass);
//set variables
$movieID = 41154;
$userID = 15;
$vote = 'yes';
//query/insert statement
$sql = "INSERT INTO votes (movieID,userID,yesNo,$vote) VALUES (:movieID,:userID, :yesNo, :$vote)";
$q = $conn->prepare($sql);
$q->execute(array(':movieID'=>$movieID,
':userID'=>$userID)),
':yesNo'=>1)),
':$vote'=>1));
Instead of using or die(), PDO also has a different way of handling errors and exceptions. You can learn more about it on PHPHash.org's Tutorial: PDO for MySQL - Error Handling.
INSERT INTO votes (movieID,userID,yesNo,$vote)
and replace $vote with vote
Related
I have a table into which new data is frequently inserted. I need to get the very last ID of the table. How can I do this?
Is it similar to SELECT MAX(id) FROM table?
If you're using PDO, use PDO::lastInsertId.
If you're using Mysqli, use mysqli::$insert_id.
If you're still using Mysql:
Please, don't use mysql_* functions in new code. They are no longer maintained and are officially deprecated. See the red box? Learn about prepared statements instead, and use PDO or MySQLi - this article will help you decide which. If you choose PDO, here is a good tutorial.
But if you have to, use mysql_insert_id.
there is a function to know what was the last id inserted in the current connection
mysql_query('INSERT INTO FOO(a) VALUES(\'b\')');
$id = mysql_insert_id();
plus using max is a bad idea because it could lead to problems if your code is used at same time in two different sessions.
That function is called mysql_insert_id
With PDO:
$pdo->lastInsertId();
With Mysqli:
$mysqli->insert_id;
Please, don't use mysql_* functions in new code. They are no longer maintained and are officially deprecated. See the red box? Learn about prepared statements instead, and use PDO or MySQLi - this article will help you decide which. If you choose PDO, here is a good tutorial.
It's ok. Also you can use LAST_INSERT_ID()
What you wrote would get you the greatest id assuming they were unique and auto-incremented that would be fine assuming you are okay with inviting concurrency issues.
Since you're using MySQL as your database, there is the specific function LAST_INSERT_ID() which only works on the current connection that did the insert.
PHP offers a specific function for that too called mysql_insert_id.
Try this should work fine:
$link = mysqli_connect("localhost", "my_user", "my_password", "world");
$query = "INSERT blah blah blah...";
$result = mysqli_query($link, $query);
echo mysqli_insert_id($link);
Clean and Simple -
$selectquery="SELECT id FROM tableName ORDER BY id DESC LIMIT 1";
$result = $mysqli->query($selectquery);
$row = $result->fetch_assoc();
echo $row['id'];
To get last inserted id in codeigniter
After executing insert query just use one function called insert_id() on database, it will return last inserted id
Ex:
$this->db->insert('mytable',$data);
echo $this->db->insert_id(); //returns last inserted id
in one line
echo $this->db->insert('mytable',$data)->insert_id();
It's ok to use mysql_insert_id(),
but there is one specific note about using it, you must call it after executed INSERT query, means in the same script session.
If you use it otherwise it wouldn't work correctly.
You can get the latest inserted id by the in built php function mysql_insert_id();
$id = mysql_insert_id();
you an also get the latest id by
$id = last_insert_id();
It's sad not to see any answers with an example.
Using Mysqli::$insert_id:
$sql="INSERT INTO table (col1, col2, col3) VALUES (val1, val2, val3)";
$mysqli->query($sql);
$last_inserted_id=$mysqli->insert_id; // returns last ID
Using PDO::lastInsertId:
$sql="INSERT INTO table (col1, col2, col3) VALUES (val1, val2, val3)";
$database->query($sql);
$last_inserted_id=$database->lastInsertId(); // returns last ID
NOTE: if you do multiple inserts with one statement mysqli::insert_id will not be correct.
The table:
create table xyz (id int(11) auto_increment, name varchar(255), primary key(id));
Now if you do:
insert into xyz (name) values('one'),('two'),('three');
The mysqli::insert_id will be 1 not 3.
To get the correct value do:
mysqli::insert_id + mysqli::affected_rows) - 1
This has been document but it is a bit obscure.
I prefer use a pure MySQL syntax to get last auto_increment id of the table I want.
php mysql_insert_id() and mysql last_insert_id() give only last transaction ID.
If you want last auto_incremented ID of any table in your schema (not only last transaction one), you can use this query
SELECT AUTO_INCREMENT FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'my_database'
AND TABLE_NAME = 'my_table_name';
That's it.
Using MySQLi transaction I sometimes wasn't able to get mysqli::$insert_id, because it returned 0. Especially if I was using stored procedures, that executing INSERTs. So there is another way within transaction:
<?php
function getInsertId(mysqli &$instance, $enforceQuery = false){
if(!$enforceQuery)return $instance->insert_id;
$result = $instance->query('SELECT LAST_INSERT_ID();');
if($instance->errno)return false;
list($buffer) = $result->fetch_row();
$result->free();
unset($result);
return $buffer;
}
?>
Use mysqli as mysql is depricating
<?php
$mysqli = new mysqli("localhost", "yourUsername", "yourPassword", "yourDB");
/* check connection */
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
// Conside employee table with id,name,designation
$query = "INSERT INTO myCity VALUES (NULL, 'Ram', 'Developer')";
$mysqli->query($query);
printf ("New Record has id %d.\n", $mysqli->insert_id);
/* close connection */
$mysqli->close();
?>
I tried
mysqli_insert_id($dbConnectionObj)
This returns the current connection's last inserted id, so if you are managing your connections properly this should work. Worked for me at least.
i have an c++ program that sending POST of logs to my server and store it on database, the problem is that the checking of duplicates before insert a new row is not working, i think that the program send the POST very fast and there is no delay between the POSTS to the server so the Mysqli can't handle this, is there any solution from server client? maybe locking rows or something?
$date = date('Y-m-d', time());
$prep_select_qa = 'SELECT * from `logs` WHERE `guid` = ? AND `error_code` = ? AND `date_create` = ?';
$select_qa = $db->prepare($prep_select_qa);
$select_qa->bind_param('sss', $_POST['guid'], $_POST['error_code'], $date);
$select_qa->execute();
$select_qa->store_result();
$num_rows = $select_qa->num_rows;
if($num_rows == 0)
{
$prep_insert_qa = 'INSERT INTO `logs` (`type`, `guid`, `sent_by`, `class_and_method`, `api_method`, `error_code`, `error_text`, `date_create`) VALUES (?,?,?,?,?,?,?,?)';
$insert_qa = $db->prepare($prep_insert_qa);
$insert_qa->bind_param('ssssssss', $new, $_POST['guid'], $_POST['sentBy'], $_POST['classAndMethodName'], $_POST['APImethod'], $_POST['ErrorCode'], $_POST['ErrorText'], $date);
$insert_qa->execute();
$insert_qa->store_result();
}
First, the answer to your question is that you are retrieving all the rows in order to count them. Presumably, this requires reading all the data in the table and returning some of it (unless you have indexes). A faster method is to check the value returned by this query:
SELECT count(*)
FROM `logs`
WHERE `guid` = ? AND `error_code` = ? AND `date_create` = ?';
And an even faster method is not to count but to determine if any row exists:
SELECT EXISTS (SELECT 1
FROM `logs`
WHERE `guid` = ? AND `error_code` = ? AND `date_create` = ?'
)
This will return 1 if the row exists and 0 otherwise. Both of the above queries and your original query will benefit from having an index on guid, error_code, date_create.
In practice, you should follow Marvin's advice and use a unique index. This means the database does the checking via a unique index rather than the application. One very important reason is a race condition. If two users are inserting the same row at the same time, both might execute the if statement, find there are no matching rows in the table, and then insert duplicate rows.
The SELECT scheme must be enclosed in a BEGIN...COMMIT transaction and have FOR UPDATE on it. Otherwise, some other connection can slip in and defeat your check.
Instead, try to do it in a single, atomic, instruction:
Once you have an INDEX that will prevent duplicates...
INSERT IGNORE -- Silently does nothing if it is a dup.
INSERT...ON DUPLICATE KEY UPDATE -- Lets you change something as you try to insert a dup.
Also, the INSERT solutions will be faster (which was your original question).
I have a table viewer with id, ip, date_last_viewed & blog_id as the columns. I'm first checking whether a particular entry having the same IP and blog_id is present or not. If yes, it updates the date. Else, it inserts a new entry.
My code is below:
$search_ip = mysql_query("SELECT ip FROM viewer WHERE ip = '".$_SERVER['REMOTE_ADDR']."' AND blog_id= '".$b_id."' ");
if ($search_ip == false){
$insert_ip = mysql_query("INSERT INTO viewer (ip, blog_id, date_last_viewed) VALUES ('".$_SERVER['REMOTE_ADDR']."', '".$b_id."', NOW())");
}
else {
$update_ip = mysql_query("UPDATE viewer SET date_last_viewed = NOW() WHERE ip = '".$_SERVER['REMOTE_ADDR']."' AND blog_id='".$b_id."' ");
}
The table is not inserting anything. What am I doing wrong here? Also, as I'm new to PHP programming, could someone tell me how to modify the above code to PDO?
You can actually do it in just one query.
MySQL has a special feature called INSERT ... ON DUPLICATE KEY UPDATE which basically insert if the record does not exist or update if it already exists. One thing you need to do is to define a unique column(/s)
INSERT ... ON DUPLICATE KEY UPDATE Syntax
Based on your statement, you need to define a unique constraint on both column,
ALTER TABLE viewer ADD CONSTRAINT vw_uq UNIQUE (ip, blog_id)
and execute this statement,
INSERT INTO viewer (ip, blog_id, date_last_viewed)
VALUES ($_SERVER['REMOTE_ADDR'], b_id, NOW())
ON DUPLICATE KEY UPDATE date_last_viewed = NOW()
As a sidenote, the query is vulnerable with SQL Injection if the value(s) of the variables came from the outside. Please take a look at the article below to learn how to prevent from it. By using PreparedStatements you can get rid of using single quotes around values.
How to prevent SQL injection in PHP?
Assuming your mysql_query executes correctly, it wont return false. What you should do is check the number of rows it returns. You can do this using mysql_num_rows.
Also, take note of the big red warning box at the top of the mysql_* man pages.
You should first add error handlers. Then move to mysqli_ and use prepared statements.
$search_ip = mysql_query( "SELECT ... " ) or die( mysql_error() );
if( mysql_num_rows($search_ip) == 0 ) {
$insert_ip = mysql_query( "INSERT ... " ) or die( mysql_error() );
}
else {
$update_ip = mysql_query( "UPDATE ... " ) or die( mysql_error() );
}
$search_ip will never == false, because it is a reference to the result. Use mysql_num_rows($earch_ip) instead. Also note that mysqli replaces this and your code is actually deprecated
That's not the right way to check if a query returned a value:
$search_ip = mysql_query("SELECT ip FROM viewer WHERE ip = '".$_SERVER['REMOTE_ADDR']."' AND blog_id= '".$b_id."' ");
if (mysql_num_rows($search_ip)==0) {
....
}
I have an enrollment form which takes consumer information, stores it in session, passes from page to page then stores in a database when finished. Originally the table simply listed fields for up to 16 persons but after reading into relational databases, found this was foolish.
I have since created a table named "members" and "managers". Each enrollment will take the information input, store the manager ID in the respective table and place a reference field in each member row containing the manager ID.
While I allow up to 16 members to be enrolled at once, this can range from 1-16.
My best guess is to use a FOR-loop to run though multiple INSERT statements in the event more than 1 member is enrolled.
In the example below, I am using the variable $num to represent the individual member's information and $total to represent the number of all members being enrolled. The code here does not function but am looking for:
a) ways to correct
b) understand if there are more 'efficient' ways of doing this type of INSERT
sample code:
<?php
$conn = mysql_connect("localhost", "username", "pw");
mysql_select_db("db",$conn);
for ($num=1; $num<=$total; $num++) {
$sql = "INSERT INTO table VALUES ('', '$clean_f'.$num.'fname', '$clean_f.$num.mi', '$clean_f.$num.lname', '$clean_f.$num.fednum', '$clean_f.$num.dob', '$clean_f.$num.ssn', '$clean_f.$num.address', '$clean_f.$num.city', '$clean_f.$num.state', '$clean_f.$num.zip', '$clean_f.$num.phone', '$clean_f.$num.email')";
$result = mysql_query($sql, $conn) or die(mysql_error());
}
mysql_close($conn);
header("Location: completed.php");
?>
If all of your statements are structurally the same, but with different parameter values, consider using the PDO extension, which supports prepared statements. The benefits of prepared statements can be read here (http://www.php.net/manual/en/pdo.prepared-statements.php), but in general, the same statement will only need to be compiled once, but can be executed as many times as you want with different parameters, which can make your script more "efficient".
Using PDO, your code could look something like:
$db = new PDO('mysql:host=localhost;dbname=db', 'username', 'pw');
$statement = $db->prepare('INSERT INTO tablename (field1, field2, field3, ...) VALUES (?,?,?,?');
for ($num=1; $num<=$total; $num++) {
$statement->execute(array('val1', 'val2', 'val3', '...'));
}
Generally, putting a query in a loop is bad thing. There is usually a better way. In this case, you should use the multi-insert syntax. Your INSERT isn't working because you didn't specify the fields. I'm assuming the lack of a space between the table name and VALUES is a typo, along with the bad quoting.
INSERT INTO table_name (field1, fname, lname, fednum, ...)
VALUES ('val1', 'Pete', 'Moss', 1234),
('val2', 'T.', 'Cupp', 54321),
('val3', 'Youdid', 'Watt', 787123);
The solution, if I read you right, is to start with the fixed query string:
$queryString = "INSERT INTO table (field1, field2, ...) VALUES ";
then run a loop to build the malleable part. Putting your values into arrays makes things easier:
$queryInsert = '';
$total = count($value1Array);
while ($i < $total) {
$queryInsert .= "('$value1Array[$i]','$value2Array[$i]','$value3Array[$i],...), ";
++$i;
}
then append to the first query piece:
$queryString = $queryString.$queryInsert;
and trim off the trailing , and you're good to go.
I'm new to php. So, please forgive me if this seems like a dumb question.
Say i have a MySQL insert statement insert into table (a,b) values (1,2),(3,4),(5,6). table 'table' has a auto increment field called 'id'.
how can I retrieve all the ids created by the insert statement above?
It will be great if i get an example that uses mysqli.
You can't. I would suggest that you maintain your own ids (using guid or your own auto-increment table) and use it when you insert into the table.
But it's possible to get the auto-increment value for the last inserted using LAST_INSERT_ID():
http://dev.mysql.com/doc/refman/5.0/en/getting-unique-id.html
AngeDeLaMort's answer is almost right. Certainly, the most appropriate way to deal with the problem is to insert one row at a time and poll the insert_id or generate the sequence elsewhere (which has additional benefits in terms of scalability).
I'd advise strongly against trying to determine the last insert_id and comparing this the most recent insert_id after the insert - there's just too may ways this will fail.
But...an alternative approach would be:
....
"INSERT INTO destn (id, data, other, trans_ref)
SELECT id, data, other, connection_id() FROM source";
....
"SELECT id FROM destn WHERE trans_ref=connection_id()";
....
"UPDATE destn SET trans_ref=NULL where trans_ref=connection_id()";
The second query will return the ids generated (note that this assumes that you use the same connection for all 3 queries). The third query is necessary because connection ids to go back into the pool when you disconnect (i.e. are reused).
C.
In some cases, if you have another identifier of sort such as a UserID, you could filter your query by UniqueID's greater than or equal to mysql_insert_id(), limit by the number of affected rows and only display those by the user. This would really only work inside of a transaction.
$SQL = "INSERT INTO Table
(UserID, Data)
VALUES
(1,'Foo'),
(1,'Bar'),
(1,'FooBar')";
$Result = mysql_query($SQL);
$LastID = mysql_insert_id();
$RowsAffected = mysql_affected_rows();
$IDSQL = "SELECT RecordID
FROM Table
WHERE UserID = 1
AND RecordID >= '$LastID'
LIMIT '$RowsAffected'";
$IDResult = mysql_query($IDSQL);
as a follow up to AngeDeLaMort:
You could seperate your inserts and do it something like this:
$data = array (
array(1,2),
array(3,4),
array(5,6)
);
$ids = array();
foreach ($data as $item) {
$sql = 'insert into table (a,b) values ('.$item[0].','.$item[1].')';
mysql_query ($sql);
$id[] = mysql_insert_id();
}
Now all your new id's are in the $id array.
Maybe I can do this
$insert = "insert into table (a,b) values (1,2),(3,4),(5,6)";
$mysqli->query($insert);
$rows_to_be_inserted=3;
$inserted_id = $mysqli->insert_id // gives me the id of the first row in my list
$last_row_id = ($inserted_id+$rows_to_be_inserted)-1;
$mysql->query("select * from table where id between $inserted_id and $last_row_id");
what to you guys say?