MySQL getting 0 from pdo lastInsertID - php

Like so many others, using the pdo lastInsertID() is only returning 0 for me. I've looked at all of the helper questions that stack Overflow puts up, searched online and I've still getting a 0. I think the code is right but I clearly missed something as I still get 0 no matter what I try.
My table has an auto-incrementing id column (named 'id'). It is also the primary key for the table. I'm using a stored procedure for the insert and so the code looks like:
$stmt = $pdo_write->prepare('CALL sp_Save_Requests(:formSecret,:ipAddress)');
$stmt->bindParam(':formSecret', $formSecret, PDO::PARAM_STR);
$stmt->bindParam(':ipAddress', $ipAddress, PDO::PARAM_STR);
$stmt->execute();
$lastID = $pdo_write->lastInsertID();
This consistently returns 0 even though a new id is available in the table - as can be seen below in the export from phpmyadmin.
I use separate connections depending if I'm selecting or inserting/updating. In this instance the connection object is:
try {
$pdo_write = new PDO("mysql:host=$myServer;dbname=$myDB", $myRW_UID, $myRW_PW);
$pdo_write->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );
$pdo_write->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$pdo_write->setAttribute( PDO::ATTR_EMULATE_PREPARES,TRUE );
} catch(PDOException $e) {
echo 'RW Connection Failed: '.$e->getMessage();
exit();
}
One possible issue - I do use a trigger to create and set a guid in the table but that is set to fire before the actual insert. The dump from phpmyadmin of the table follows though the name of the real table has been changed.:
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET AUTOCOMMIT = 0;
START TRANSACTION;
SET time_zone = "+00:00";
-- Table structure for table `tbl_test`
CREATE TABLE `tbl_test` (
`id` int(10) NOT NULL,
`guid` varchar(100) NOT NULL,
`formSecret` varchar(100) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Triggers `tbl_test`
--
DELIMITER $$
CREATE TRIGGER `tr_TestRequests_GUID` BEFORE INSERT ON `tbl_test` FOR EACH ROW SET NEW.guid = UUID()
$$
DELIMITER ;
--
-- Indexes for table `tbl_test`
--
ALTER TABLE `tbl_test`
ADD PRIMARY KEY (`id`),
ADD UNIQUE KEY `guid` (`guid`),
ADD UNIQUE KEY `id` (`id`);
--
-- AUTO_INCREMENT for table `tbl_test`
--
ALTER TABLE `tbl_test`
MODIFY `id` int(10) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=44;
COMMIT;
I would prefer to not use a select to pull the ID if I don't have to. But, I'm stumped and hope that someone can see what I'm missing. Many thanks in advance for any help.

Turns out I had a syntax error in the id assignment to the out variable. Took forever to see it but it works now.
Thanks for the feedback and making me go back through this once again.

Related

Oracle SQL Trigger Error- OCI_SUCCESS_WITH_INFO: ORA-24344

I am using a trigger called "users_id_trigger" to auto increment the users.user_id column.
But in Object Browser its status is showing invalid!
I am working on a PHP project where i am getting this error while i run the query from a PHP script. here is the error message:
oci_execute(): OCI_SUCCESS_WITH_INFO: ORA-24344: success with compilation error
Here is my method to create the entire table and related SEQUENCE and TRIGGER to be able to have auto increment feature in the user_id column.
public function create_users_table()
{
// creating users table
oci_execute(oci_parse($this->conn, "CREATE TABLE users(
user_id NUMBER(10) NOT NULL,
user_name VARCHAR2(100) NOT NULL,
user_password VARCHAR(100) NOT NULL,
user_email VARCHAR(100) NOT NULL,
user_location VARCHAR(100) NOT NULL,
CONSTRAINT users_pk PRIMARY KEY (user_id)
)"));
// creating users sequence
oci_execute(oci_parse($this->conn, "CREATE SEQUENCE users_seq
MINVALUE 1
START WITH 1
INCREMENT BY 1
NOCACHE;
"));
// creating user sequence trigger
echo oci_execute(oci_parse($this->conn, "CREATE OR REPLACE TRIGGER users_id_trigger
BEFORE INSERT ON users
FOR EACH ROW
BEGIN
:new.user_id := users_seq.nextval;
END;
"));
}
What i am doing wrong? because the table and sequence is created successfully but not the trigger.
EDIT:
while inserting a new row i got this error:
insert into users values(1, 'hasan', '1234',
'hdg#live.com', 'Dhaka, Bangladesh')
* ERROR at line 1: ORA-04098: trigger 'FLIPLISTS.USERS_ID_TRIGGER' is invalid and failed re-validation
Oracle Version i am using: Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production (Windows 10)
Compilation Error: ORA-04082: NEW or OLD references not allowed in table level triggers
If oracle version that you are using is less than 11g then Modify your trigger as below
CREATE OR REPLACE TRIGGER users_id_trigger
BEFORE INSERT ON users
FOR EACH ROW
BEGIN
select users_seq.nextval into :new.user_id from dual ;
END;
The issue is that you have newlines on windows,so remove them.
echo oci_execute(oci_parse($this->conn, trim(preg_replace('/\s+/', ' ', "CREATE OR REPLACE TRIGGER users_id_trigger
BEFORE INSERT ON users
FOR EACH ROW
BEGIN
:new.user_id := users_seq.nextval;
END;
"));));

LIKE % XX(YY)GG % not working in MySQL

I have used Stored procedure to check whether a name exist in a table or not by using the following code snippet..
BEGIN
IF ids = 0 THEN
SELECT * FROM table_name WHERE `table_id` = alb_id AND name LIKE CONCAT('%',var_name,'%');
END IF;
END
I got the solution if the name doesn't contain any special characters or brackets, like XXXX.
If the name contains any brackets means result not came, like XX(YY)GG.
Suggest me for the best solution
Edited:
In this if a name exist already i should not insert it again, for this condition i used this procedure. If it returns mysql_num_rows > 0 means i wont insert, else i will insert the name into my table..
My sample names are,..
Turning Tables (Live Acoustic)
Hiding My Heart
Someone Like You (Live Acoustic)
Right Now (Na Na Na)
Keep You Much Longer
Someone Like You
In the list of name "Someone Like You" and "Someone Like You (Live Acoustic)" are two different names, i want to identify the name "Someone Like You (Live Acoustic)" is already exist or not..
How do i do?
CREATE TABLE `stack_test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`text` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB CHARSET=utf8;
INSERT INTO `blur_new`.`stack_test` (`id`, `text`) VALUES ('1', 'run (rabbit) run');
INSERT INTO `blur_new`.`stack_test` (`id`, `text`) VALUES ('2', 'test');
set #a = 'n (rabbit)';
select * from stack_test where text like concat('%',#a,'%');
results in:
1 |run (rabbit) run
So, it works.
check the rest of the conditions in where clause
check how are you passing the value
you might gonna have to check you data types. I have a feeling something is not right there

oci_execute(): OCI_SUCCESS_WITH_INFO: ORA-24344 using a trigger/sequence to auto increment an oracle table error

I'm using a sequence and trigger to essentially auto increment a column in a table, however I'm getting an error - ORA-24344: success with compilation error.
I was using this post: How to create id with AUTO_INCREMENT on Oracle? and it worked successfully for two other tables w/ auto increment I made, but there must be something in here I'm not familiar with causing an error.
More edits: Thanks to Polppan we've established that this likely isn't an Oracle issue, rather an OCI with PHP issue. I'm using:
oci_execute($sql);
And as mentioned here (again, thanks Polppan for that link), there's a bit of an issue between EOL characters and oci_execute. It was 11 years ago, so I don't know if that's been patched or not, and I did try his solution but it didn't help. Does anyone know if there are other issues with oci_execute and creating triggers?
Creating the table: (works)
CREATE TABLE RT_documents (
documentID INT NOT NULL,
reviewID varchar2(20) NOT NULL,
file_location CLOB NOT NULL,
version NUMBER(*,3) NOT NULL,
CONSTRAINT RT_documents_pk PRIMARY KEY (documentID)
)
Creating the sequence: (works)
CREATE SEQUENCE rt_documents_seq
Creating/replacing trigger: (doesn't work)
CREATE OR REPLACE TRIGGER rt_documents_bir
BEFORE INSERT ON RT_documents
FOR EACH ROW
BEGIN
SELECT RT_documents_seq.NEXTVAL
INTO :new.documentID
FROM dual;
END;
EDIT: Exact error message as requested - (Note, I'm executing these query-by-query using OCI/Oracle in PHP. PHP tag added just in case, but pretty sure this is an oracle syntax error or something).
Error:
Notice: oci_execute(): OCI_SUCCESS_WITH_INFO: ORA-24344: success with
compilation error in (...)
-I can successfully execute the first two queries, and double checked and the table is there so it worked properly.
Trigger doesn't understand new.id as id doesn't exist in RT_documents table.
Your trigger should be
CREATE OR REPLACE TRIGGER rt_documents_bir
BEFORE INSERT
ON RT_documents
FOR EACH ROW
BEGIN
SELECT RT_documents_seq.NEXTVAL INTO :new.documentID FROM DUAL;
END;
Update
SELECT * FROM v$version;
Oracle Database 10g Enterprise Edition
CREATE TABLE RT_documents
(
documentID INT NOT NULL,
reviewID VARCHAR2 (20) NOT NULL,
file_location CLOB NOT NULL,
version NUMBER (*, 3) NOT NULL,
CONSTRAINT RT_documents_pk PRIMARY KEY (documentID)
);
Table created.
CREATE SEQUENCE rt_documents_seq;
Sequence created.
CREATE OR REPLACE TRIGGER rt_documents_bir
BEFORE INSERT
ON RT_documents
FOR EACH ROW
BEGIN
SELECT RT_documents_seq.NEXTVAL INTO :new.documentID FROM DUAL;
END;
/
Trigger created.
INSERT INTO RT_documents (reviewID, file_location, version)
VALUES ('test', 'test', 1);
1 row created.
SELECT * FROM RT_documents;
DOCUMENTID REVIEWID FILE_LOCATION
VERSION
---------- -------------------- -------------------------------------------
-------------------------------- ----------
1 test test
1
Thanks to Polppan.
The solution was removing the EOL characters. (I did try this but had, without realising, removed the semi-colons, which caused the same error code)
This was a PHP error after all. Using oci_execute, you must remove EOL characters in triggers:
$sql = "CREATE OR REPLACE TRIGGER ......."; //shortened for easy reading
$sql = str_replace(chr(13),'',$sql);
$sql = str_replace(chr(10),'',$sql);
oci_execute($sql);

PDO insert into two tables with FK data

I have two tables
CREATE TABLE angos
(
id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
angos varchar(255) not null,
grammar varchar(3) not null,
updated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT unique_input UNIQUE (angos)
) engine=InnoDB;
CREATE TABLE english
(
id int primary key,
angos_id int,
english varchar(255),
grammar_note varchar(500),
CONSTRAINT fk_angos_source FOREIGN KEY (angos_id) REFERENCES angos(id)
) engine=InnoDB;
...and some csv data that I have stored in a php array. I'm trying to insert the array data into two mysql tables, one of which has a fk of the other. I'm using php PDO for the insert. This is what I have...
$sql = <<<'EOD'
BEGIN;
INSERT INTO angos
(angos, grammar)
VALUES
(:angos, :grammar);
INSERT INTO english
(angos_id, english)
VALUES
(:angos_id, :english);
COMMIT;
EOD;
try
{
$q = $handler->prepare($sql);
foreach($csv as $value)
{
$q->execute(
array(
':angos' => $value[0],
':grammar' => 'con',
':english' => $value[1],
':angos_id' => 'LAST_INSERT_ID()'
)
);
}
}
catch(PDOException $e)
{
die( "Error: \n" . $e->getMessage() );
}
...the data fails to insert and the error message I'm currently getting is
Error: SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll().
Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute.
What's happening?
By default you can only execute one query at once with PDOStatement::execute() method. If you like to use transactions have a look at the PDO::beginTransaction(), PDO::commit() and PDO::rollBack() methods of PDO. And create two separated queries.
But as you're told by PHP you can set the attribute PDO::MYSQL_ATTR_USE_BUFFERED_QUERY to run multiple queries in one prepared statement. But you could run intro trouble if you change the PDO driver e.g. from MySQL to PostgreSQL. Because PostgreSQL does not support the attribute mentioned above. So I suggest that you only use one statement per prepared statement. That makes the prepared statements also more reusable than a specfic construct of statements.

PHP & MySQL, Good query is failing

I am having an odd issue with PHP and MySQL.
In attempt to create a table from PHP, I have pasted in the query I need, which executes successfully outside of the PHP environment, into PHP.
$CREATE_PAGES = "DROP TABLE IF EXISTS `MyDatabase`.`pages`;
CREATE TABLE `MyDatabase`.`pages` (
`Page_ID` int(10) unsigned NOT NULL AUTO_INCREMENT,
`Page_File` varchar(1000) NOT NULL,
`Page_Description` varchar(1000) NOT NULL,
`Page_Message` longtext NOT NULL,
PRIMARY KEY (`Page_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;";
$result= mysql_query($CREATE_PAGES,$link);
if(!($result)){
echo mysql_error();
echo $CREATE_PAGES;
}
Then I get the standard error message
. . . for the right syntax to use near 'CREATE TABLE `MyDatabase`.`pages` ( `Page_ID` int(10) unsigned NOT NULL' at line 2
However, the odd part is that when I echo the query $CREATE_PAGES I can copy and paste and it will execute just fine. How can it be a syntax error?
I know that it is not a connection error, I can pull data from another table in that database.
Is there something I am missing?
PHP call to mysql_query allows only one action at the time (as a part of SQL injection prvention I guess) so you have to split your query into two parts and call mysql_query twice.
The mysql_query() function can only execute one query at a time, whereas you can execute an arbitrary number at the command line.
From the documentation:
mysql_query() sends a unique query (multiple queries are not supported) to the currently active database on the server that's associated with the specified link_identifier.
To overcome this:
$dropTable = "DROP TABLE IF EXISTS `MyDatabase`.`pages`";
mysql_query($dropTable, $link);
$createPages ="CREATE TABLE `MyDatabase`.`pages` (
`Page_ID` int(10) unsigned NOT NULL AUTO_INCREMENT,
`Page_File` varchar(1000) NOT NULL,
`Page_Description` varchar(1000) NOT NULL,
`Page_Message` longtext NOT NULL,
PRIMARY KEY (`Page_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;";
$result = mysql_query($createPages, $link);
if(!($result)) {
echo mysql_error();
}
From docs to mysql_query:
mysql_query() sends a unique query (multiple queries are not
supported) to the currently active database on the server that's
associated with the specified link_identifier.
mysql_query can only execute a single query, it doesn't support execution of multiple queries. It's also recommended to not end your query with a semicolon.
Look for more information in the PHP documentation.

Categories