Why doesn't PDO's Oracle driver implement lastInsertId()? - php

I get this error in PDO:
error: Message: PDO::lastInsertId() [pdo.lastinsertid]:
SQLSTATE[IM001]: Driver does not support this function: driver does
not support lastInsertId()
when trying to get last inserted id from an oracle database. I added the sequence string to the last insert id function but still not working. Google doesn't say much regarding this error on Oracle with PDO.

Oracle doesn't have autoincrement columns, so lastInsertId isn't supported in the same way as for MySQL. You have to implement the equivalent "by hand" using Oracle sequences.
Create an oracle sequence for every table that requires it, and use NEXTVAL to retrieve it whenever you need to do an insert, then use that value when inserting in the table.
$sh = $conn->prepare('SELECT uid_seq.NEXTVAL AS nextInsertID FROM DUAL');
$sh->execute();
$nextInsertId = $sh->fetchColumn(0);
$sh = $conn->prepare("INSERT INTO table (id, data) VALUES(?, 255)");
$sh->execute(array($nextInsertId));

In Oracle, you should have created an oracle sequence for tables which requires an auto increment column.
If you want to insert, then you can do it in the same time rather than query nextIncrementId and insert as below:
$sh = $conn->prepare("INSERT INTO table (id, data) VALUES(SEQUENCE_NAME.NEXTVAL, ?)");
$sh->execute(array($valueToBeInsertedInDataColumn));
If you just want to know the last insert id, then don't use nextval because whenever you call it, it increment the value to the next one. You should use CURRVAL for that purpose. Below is an example:
$sh = $conn->prepare("SELECT SEQUENCE_NAME.CURRVAL AS lastInsertId FROM DUAL");
$lastInserId = $sh->execute();
Debug: print_r($lastInserId);

Related

Geometry field issue with MariaDB and PHP prepared statement

From a PHP script, using mysqli prepared statement to INSERT a row, I'm getting an error returned from MariaDB on a field of type POINT. Code looks a something like this:
$sql = 'INSERT INTO reports (location) VALUES (?)';
$stmt = $mysqli->prepare($sql);
$stmt->bind_param('s', $variable);
$variable = 'POINT(10,10)';
$stmt->execute();
location is intended to store GPS co-ordinates and is defined as point data type in it's column definition. The error which is returned in the resulting stmt object has errno = 1416 error = Cannot get geometry object from data you send to the GEOMETRY field.
Other columns of varchar type work without issue, so I'm guessing it is somewhere in the underlying table definition being POINT data type and the presentation of the intended data POINT (10, 10) as a string type in the prepared statement. I had initially thought about just storing lat, lon as individual DECIMAL columns but the POINT data type may serve future purposes much better.
In the MariaDB monitor, the statement:
INSERT INTO reports (location) VALUES (POINT(10,10));
will work fine and insert the row into the database table.
Also, if I were to use mysqli_query (which I don't intend using) as follows;
$variable = 'POINT(20, 20)';
$sql = "INSERT INTO reports (location) VALUES ($variable)";
mysqli_query($mysqli, $sql)
it works as intended.
So, my query is how in PHP, to replicate the working MariaDB monitor statement or mysqli_query() example via a mysqli prepared statement.
POINT isn't a string, it's an SQL function. MariaDB isn't smart enough to convert strings to SQL, so you cannot bind it as a string. You can bind the parameters of POINT but not the SQL itself.
The following should work fine:
$sql = 'INSERT INTO reports (location) VALUES (POINT(?,?))';
$stmt = $mysqli->prepare($sql);
$stmt->execute([10,10]);

SQL, how to get the automated ID from the previous INSERT?

I am using PHP and SQL and trying to insert user data into two tables upon registration. First in the user_table and second into the character_table. I'm using an automatically generating user_id to link the tables and need to get the value of the user_id from the first INSERT (into user_table) then add it to a column in the character_table.
I tried a few methods and here is where I ended ($username, $email, $password and $character are defined above);
$sql = "INSERT INTO
user_table (id, username, email, password)
VALUES ('NULL', '".$username."', '".$email."', '".$password."')
INSERT INTO
character_table (name, id)
VALUES ('".$character."', 'LAST_INSERT_ID()')";"
I want "id" from user_table to match with "id" inserted into character_table.
When I run the above, nothing seems to be happening. Previous attempts I always ended with id = 0. What is the correct way I can get the ID from the first INSERT?
Run your statements seperately. You run your insertion into your user_table, then grab the id then run your insertion into your character_table
You can grab the id using mysql_insert_id after running the insert. Note that on the php webpage detailing the mysql_insert_id function that it is deprecated as is all mysql* functions. Which leads to...
For the love of everything holy don't concatenate your variables directly to your INSERT statement. Switch to mysqli* functions or PDO if you haven't already and use prepared statements (parameterizing the query). If you build an application using mysql it means you are not parameterizing your queries which means you are at a huge risk for a sql injection attack.
If/when you switch over to mysqli or PDO functions you will find an equivalent mysqli_insert_id() (or PDO::lastInsertID()) function

Using the data of the index column I just added

I was just reading about PDO::lastInsertId from the PHP documentation, but after some tests I reallized I absolutelly suck at PHP xD and I should investigate more about classes and static methods and more to even understand where to put that code.
Anyway, I'm not actually trying to know the last Inserted Id, I want to get the Index value of the last inserted row of MySQL table. My Index column is called "id" and is set to auto increment everytime I add a new row, yet, when I delete a row the number doesn't update, so the value in the row called "id" may not allways be the same as the row number.
Here is the code that inserts a new row.
<?php
require('conexion.php');
$name=$_POST['name'];
$email=$_POST['email'];
$pass=$_POST['pass'];
$localidad=$_POST['localidad'];
$saldo=$_POST['saldo'];
$slastupdate=$_POST['slastupdate'];
$query="INSERT INTO usuarios (name, email, pass, localidad, saldo, slastupdate) VALUES ('$name','$email','$pass','$localidad','$saldo','$slastupdate')";
$resultado=$mysqli->query($query);
?>
Update: For now on, I'm using another query to get the last inserted's row Id... In my case using PDO is not necessary since I'm developing a private app, and there's no risk of mysql injections
require_once "../php/new_mysql.php";
$query="INSERT INTO clientes (gira, localidad, nombre, email, proxivisi, saldo) VALUES ('$gira', '$localidad', '$nombre', '$email', '$proxivisi', '$saldo')";
$agregar=$mysql->query($query) or die(mysql_error());
$querygetid=$mysql->query("SELECT id, proxivisi FROM clientes WHERE nombre='$nombre' AND email='$email'");
$getid=$querygetid->fetch_assoc();
$id=$getid['id'];
#FranCano use #user to notify us of your reply.
Your first problem is you seem to be using mysqli, not PDO in the above code. mysqli and PDO are different APIs to run MySQL queries and don't share functions. PDO::lastInsertId will give you the auto increment value of the last inserted row.
Start with PDO::__construct() to see how to start a PDO instance and connect to a database. Check PDO::query() and the examples listed to see how PDO works. However, PDO::query() is basic and does not protect you from SQL injections. For your above query you should be used prepared statements since you use user input (POST). Prepared statements are started with PDO::prepare(). MySQLi has prepared statements too but they are slightly different.
PDO is object oriented, you can't just call PDO::query() and PDO::lastInsertId(). You create a PDO instance to connect to the database, then you create a PDOStatement object by using prepare(), then you execute (PDOStatement::execute) that PDOStatement object to run the query. Then you can resort to the lastInsertId() on the original PDO object.
If you don't know OOP or object oriented programming then this will all sound pretty confusing so that is where you need to start your reading.
A quick example is:
$pdo = new PDO(..mysql connection information..);
// Create a PDOStatement object
$stmt = $pdo->prepare("INSERT into test ('field1', 'field2') VALUES (?, ?)");
// Execute the prepared statement safely inserting the post variables into the ?'s. This protects against SQL injection attacks.
if ($stmt->execute(array($_POST['value1'], $_POST['value2']))) {
$id = $pdo->lastInsertId();
}

how to insert data into 2 different tables (php mysql)

2 Tables:
1. BOOKS_IN
BOOKS_in_ID,
DATE,
USERID
2. BOOKS_IN_DETAIL
BOOKS_in_ID,
BOOK_ID,
STOCK
BOOKS_in_ID is a primary key and i need BOOKS_in_ID is automatically insert into BOOKS_IN_DETAIL.
Here, is it possible to insert records into 2 table using single query?
thankyou for your advise.
You need to call the appropriate method to get the last inserted id.
Assuming you use PDO, you need to call the method lastInsertId. $books_in_id = $pdo->lastInsertId();
If you use mysqli_* extension that's $books_in_id = $mysqli->insert_id;
EDIT: if you use the mysql_* version ( which is deprecated), upgrade first to mysqli_* , or check in the documentation
You still need two INSERT statements, but it sounds like you want to get the IDENTITY from the first insert and use it in the second, in which case, you might want to look into OUTPUT or OUTPUT INTO: http://msdn.microsoft.com/en-us/library/ms177564.aspx
Src and possible duplicate of: SQL Server: Is it possible to insert into two tables at the same time?
You can also use LastInsertId() for PDO.
A small example:
$sql = "INSERT INTO city (`city`) VALUES ('Paris') ON DUPLICATE KEY UPDATE `city` = 'Paris";
$dbh->query($sql);
echo $dbh->lastInsertId();
Src: http://php.net/manual/en/pdo.lastinsertid.php
Or get the last insert ID in mysqli:
$query = "INSERT INTO myCity VALUES (NULL, 'Stuttgart', 'DEU', 'Stuttgart', 617000)";
$mysqli->query($query);
printf ("New Record has id %d.\n", $mysqli->insert_id);
Src: http://php.net/manual/en/mysqli.insert-id.php
Do you have to stick to mysql? Because if you can use mysqli you can use multi_query(), which lets you execute multiple queries at once.
Link : http://php.net/manual/en/mysqli.quickstart.multiple-statement.php
No,Its not possible with only one INSERT query.
You can follow these steps
Write two different queries and execute them
Create Stored Procedure that execute two INSERT queried
For point One you can useLAST_INSERT_ID() function to add foreigh key

PDO: Is lastInsertId() a separate query?

If I have this code:
<?php
$q = $sql->prepare("INSERT INTO `table` (row) VALUES ('1')");
$q->execute();
$lastid = $sql->lastInsertId(); // is this a 2nd query?
?>
Would it run as two separate SQL queries?
If so, is there a way to do it in one?
$lastid = $sql->lastInsertId();
it works like a query because it will select from database the last inserted id.
as the documentation said
Returns the ID of the last inserted row, or the last value from a sequence object, depending on the underlying driver.
No, in fact it doesn't run an SQL query.
Here's the line from ext/pdo_msyql/mysql_driver.c:
char *id = php_pdo_int64_to_str(mysql_insert_id(H->server) TSRMLS_CC);
This is a call to the MySQL API, mysql_insert_id(). This internally accesses the last insert id as a property, not by running SQL.

Categories