PHP & MySQL, Good query is failing - php

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.

Related

MySQL getting 0 from pdo lastInsertID

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.

mysql lock tables causing certain inserts to fail randomly

I recently adding locking to a query to prevent a deadlock. This problem is solved, but now I am having a problem where inserts into one table are randomly failing with no cause. I
I have turned on the general query log to see exactly what is happening. Is there any other way to debug this to see exactly what is happening or have any ideas of the cause?
If I perform the following lock:
$this->db->query('LOCK TABLES '.$this->db->dbprefix('customers').' WRITE, '.$this->db->dbprefix('sales').' WRITE,
'.$this->db->dbprefix('store_accounts').' WRITE, '.$this->db->dbprefix('sales_payments').' WRITE, '.$this->db->dbprefix('sales_items').' WRITE,
'.$this->db->dbprefix('giftcards').' WRITE, '.$this->db->dbprefix('location_items').' WRITE,
'.$this->db->dbprefix('inventory').' WRITE, '.$this->db->dbprefix('sales_items_taxes').' WRITE,
'.$this->db->dbprefix('sales_item_kits').' WRITE, '.$this->db->dbprefix('sales_item_kits_taxes').' WRITE,'.$this->db->dbprefix('people').' READ,'.$this->db->dbprefix('items').' READ
,'.$this->db->dbprefix('employees_locations').' READ,'.$this->db->dbprefix('locations').' READ, '.$this->db->dbprefix('items_tier_prices').' READ
, '.$this->db->dbprefix('location_items_tier_prices').' READ, '.$this->db->dbprefix('items_taxes').' READ, '.$this->db->dbprefix('item_kits').' READ
, '.$this->db->dbprefix('location_item_kits').' READ, '.$this->db->dbprefix('item_kit_items').' READ, '.$this->db->dbprefix('employees').' READ , '.$this->db->dbprefix('item_kits_tier_prices').' READ
, '.$this->db->dbprefix('location_item_kits_tier_prices').' READ, '.$this->db->dbprefix('location_items_taxes').' READ
, '.$this->db->dbprefix('location_item_kits_taxes'). ' READ, '.$this->db->dbprefix('item_kits_taxes'). ' READ');
foreach($items as $line=>$item)
{
if (isset($item['item_id']))
{
$cur_item_info = $this->Item->get_info($item['item_id']);
$sales_items_data = array
(
'sale_id'=>$sale_id,
'item_id'=>$item['item_id'],
'line'=>$item['line'],
'description'=>$item['description'],
'serialnumber'=>$item['serialnumber'],
'quantity_purchased'=>$item['quantity'],
'discount_percent'=>$item['discount'],
'item_cost_price' => $cur_item_info->cost_price,
'item_unit_price'=>$item['price']
);
$this->db->insert('sales_items',$sales_items_data);
}
...
...
}
$this->db->query('UNLOCK TABLES');
Table:
+--------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| phppos_sales_items | CREATE TABLE `phppos_sales_items` (
`sale_id` int(10) NOT NULL DEFAULT '0',
`item_id` int(10) NOT NULL DEFAULT '0',
`description` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`serialnumber` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`line` int(3) NOT NULL DEFAULT '0',
`quantity_purchased` decimal(23,10) NOT NULL DEFAULT '0.0000000000',
`item_cost_price` decimal(23,10) NOT NULL,
`item_unit_price` decimal(23,10) NOT NULL,
`discount_percent` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`sale_id`,`item_id`,`line`),
KEY `item_id` (`item_id`),
CONSTRAINT `phppos_sales_items_ibfk_1` FOREIGN KEY (`item_id`) REFERENCES `phppos_items` (`item_id`),
CONSTRAINT `phppos_sales_items_ibfk_2` FOREIGN KEY (`sale_id`) REFERENCES `phppos_sales` (`sale_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci |
+--------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.06 sec)
Then insert into a bunch of tables but randomly I am getting an error where data does NOT make it into sales_items, but correctly makes it into other tables using the item_id foreign key...is there a scenario that can causes inserts to fail randomly because of the locks? I am going to turn on the general query log to see what is happening but I cannot track it down. This never happened before until I added the locking.
Turned out it was related to mysql 5.6 default strict mode setting. Not related to lock

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.

Is the method Doctrine_Table::find() deprecated?

I had a problem with the method Doctrine_Table::find(), since it's thorowing an exception of
SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens
I solved the problem by using Doctrine::getTable('City')->findOneById($id); instead and it works fine.
When I tried to invistigate about the problem I was surprised since no documentation about the method Doctrine_Table::find() in the official website.
Any one knows what's the problem? is it deprecated?
BTW it's exists on the actual code! of the version (1.2.1).
more info about the database:
CREATE TABLE IF NOT EXISTS `country` (
`id` INT NOT NULL AUTO_INCREMENT ,
`name` VARCHAR(64) NOT NULL ,
PRIMARY KEY (`id`) )
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_unicode_ci;
CREATE TABLE IF NOT EXISTS `city` (
`id` INT NOT NULL AUTO_INCREMENT ,
`name` VARCHAR(64) NOT NULL ,
`country_id` INT NOT NULL ,
PRIMARY KEY (`id`, `country_id`) ,
INDEX `fk_city_country` (`country_id` ASC) ,
CONSTRAINT `fk_city_country`
FOREIGN KEY (`country_id` )
REFERENCES `country` (`id` )
ON DELETE CASCADE
ON UPDATE NO ACTION)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_unicode_ci;
What's weird is that both Doctrine_Table::find(), and Doctrine_Table::findOneById() works fine on Country table!.
PS: I realize that Doctrine_Table::findOneById() is a __call() generated method. And that make me confused more, why the actual find() method can't behave as expected (is my expectation wrong or what)!
Oh my bad. I didnt see it earlier, shame on me =p
Your table has two primary keys (id and country_id), so the find method requires you to pass both parameters to the find method.
You could instead use the magic methods:
Doctrine::getTable('City')->findOneById(1)
As of v 1.2.1, Doctrine_Table::find() is NOT deprecated
You can check the official documentation on http://www.doctrine-project.org/documentation/manual/1_2/en/component-overview#table:finder-methods
As for the "invalid parameter number" error, it means you query has more or fewer parameters than expected, most often you used a token (?) and forgot to add the parameter to it
Doctrine_Query::create()
->from('User u')
->where('u.name = ?', 'Jonh')
->andWhere('u.is_active = ?')
The example i used have two tokens '?', but only one parameter 'jonh', it would throw the same error: "Invalid parameter number: number of bound variables does not match number of tokens"

What's wrong with this PHP-MySQL CREATE TABLE query?

First, I'm just starting to learn MySQL with PHP.
My query copy/paste directly from my IDE:
$query = "CREATE TABLE IF NOT EXISTS $table_messages (
id int(11) unsigned NOT NULL auto_increment,
show tinyint(1) unsigned NOT NULL default '0',
to varchar(255) NOT NULL default '',
from varchar(255) NOT NULL default '',
type varchar(255) NOT NULL default '',
message varchar(255) NOT NULL default '',
PRIMARY KEY(id)
) DEFAULT CHARSET=utf8 AUTO_INCREMENT=1";
$result = mysql_query( $query, $link ) OR exit ( mysql_error() );
Results in this error:
You have an error in your SQL syntax;
near 'show tinyint(1) unsigned NOT
NULL default '0' , to varchar(255) N'
at line 4
... so I add one character to show (e.g. showz) and get this error:
You have an error in your SQL syntax;
near 'to varchar(255) NOT NULL
default '' , from varchar(255) NOT
NUL' at line 5
... so I add one character to to (e.g. toz) and get this error:
You have an error in your SQL syntax;
near 'from varchar(255) NOT NULL
default '' , type varchar(255) NOT NU'
at line 6
... so I add one character to from (e.g. fromz) and IT WORKS!?
What is going on? Lol
If this question is too blatantly obvious, I'll remove it if the community thinks it would be prudent, but in the meantime I'm stumped.
BTW, I've messed with spacing, case and other things without any success.
SHOW, TO and FROM are reserved MySQL keywords. You must quote them with backticks to make them work as column names:
$query = "CREATE TABLE IF NOT EXISTS $table_messages (
`id` int(11) unsigned NOT NULL auto_increment,
`show` tinyint(1) unsigned NOT NULL default '0' ,
`to` varchar(255) NOT NULL default '' ,
`from` varchar(255) NOT NULL default '' ,
`type` varchar(255) NOT NULL default '' ,
`message` varchar(255) NOT NULL default '' ,
PRIMARY KEY(id)
) DEFAULT CHARSET=utf8 AUTO_INCREMENT=1";
It's usually good practice (though unneeded) to quote every column name this way to prevent accidental collisions with keywords as there are hundreds of them. For a full list, see http://dev.mysql.com/doc/refman/5.1/en/reserved-words.html.
You might be interested in this list of reserved words in MySQL statements. In short, if you want to use any of these as a column name (or anywhere in following queries), you have to quote them, usually in backticks:
`show` TINYINT(1) UNSIGNED NOT NULL,
...and later:
SELECT `show` FROM `varchar` WHERE `to`="France"
Just a stab in the dark, but are to and from reserved words in mysql? Could you either wrap those words in [] like [to] and [from] or, like you did, change the terms to toperson or fromperson?
This is not the answer to your problem, but it's the answer to "What's wrong with a PHP-MySQL CREATE TABLE query?" (for another googler)
Maybe not all versions of PHP are like this, but in my environment, non PDO commands like "mysql_query" throws an error when I try to make a table:
CREATE TABLE IF NOT EXISTS `actionlog`
Error:
You have an error in your SQL syntax
Works just fine with the PDO adapter.

Categories