Simple: creating tables in database - php

Really simple question. I forgot how to deal with this specific script. With a PHP file I create tables in mysql database. I have $query variable with the following commands:
$query = "CREATE TABLE IF NOT EXISTS `table1` (
`id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
`status` int(11) NOT NULL
)ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `table2` (
`something` varchar(100) NOT NULL,
`whatever` text NOT NULL
)ENGINE=MyISAM DEFAULT CHARSET=utf8;
";
It works only if I exec one single command. When I run multiple CREATE / INSERT / DROP ... commands it doesn't work. For sure there's a mistake with the syntax maybe ; and ,.

mysql_query() doesn't support multiple statements in the same call.
http://php.net/manual/en/function.mysql-query.php
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.

You're problem doesn't comes from the SQL (well, I didn't checked it properly to be honest), but from mysql_query (assuming you're using it) : it does't allow multiple request.
http://php.net/manual/fr/function.mysql-query.php

As others have stated, the mysql_query() function doesn't support multiple queries in a single call.
On a somewhat related note, if you are able you should look into using mysql_i or PDO in place of the old mysql_*() functions, which are inferior for too many reasons to list here.
http://php.net/manual/en/book.mysqli.php
http://php.net/manual/en/book.pdo.php

Related

MyISAM racing conditions / LOCK TABLES

My 'invoices' table:
CREATE TABLE `invoices` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`invoice_id` int(11) NOT NULL,
PRIMARY KEY (`id`,`invoice_id`),
UNIQUE KEY `invoice_id` (`invoice_id`),
KEY `order_id` (`order_id`)
) ENGINE=MyISAM AUTO_INCREMENT=115 DEFAULT CHARSET=utf8
When I try the query :
mysqli_query($conn, "LOCK TABLES 'invoices' WRITE");
in a php script, it doesn't work as I can insert a new row in the "locked" table using phpMyAdmin's SQL console during lock time.
May I be totally confident that a query like this
INSERT INTO `invoices` (`invoice_id`) SELECT MAX(`invoice_id`)+100 FROM `invoices`
can successfully prevents race conditions so to use this instead of a LOCK TABLES query;
NOTES:
I did not create this table.
I may not alter the table.
When you write an sql query you should be wrap table|column names with back ticks but not single quotes.
In your case
mysqli_query($conn, "LOCK TABLES `invoices` WRITE");
Note But I would recommend you to stop trying to "resolve" racing condition. Why did you decide that it is a problem in your case?
Racing condition could be a big problem for some projects. But I doubt that it is your case. I would support #Dave comment, you already have auto incremented index. That is more than enough in many cases.
Imho you don't need this "locks".
INSERT INTO `invoices` (`invoice_id`) SELECT MAX(`invoice_id`)+100 FROM `invoices`
This query has almost no sense. Could you explain why are you trying to do this weird insert?
Please note that the lock only lasts for the duration of your database session - in this case the duration of your script call.

How to fix SQL error with dropping a table in PHP?

I have created a web you can upload and download files - everything works perfect. But now, I want to create a init file, that delete old records in database and create a new tables in it.
So I write this:
$command = "
IF OBJECT_ID(`".$database.".Users`) IS NOT NULL
DROP TABLE ".$database.".Users;
IF OBJECT_ID(`".$database.".Uploads`) IS NOT NULL
DROP TABLE ".$database.".Uploads;
CREATE TABLE `Users` (
`Id` int(11) NOT NULL,
`User` text NOT NULL,
`Password` text NOT NULL,
`Permission` int(11) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;
ALTER TABLE `Users` ADD PRIMARY KEY (`Id`);
ALTER TABLE `Users` MODIFY `Id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=0;
CREATE TABLE `Uploads` (
`Id` int(11) NOT NULL,
`Name` text NOT NULL,
`User` text NOT NULL,
`Comment` text NOT NULL,
`Path` text NOT NULL,
`Permission` int(11) NOT NULL,
`Date` text NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;
ALTER TABLE `Uploads` ADD PRIMARY KEY (`Id`);
ALTER TABLE `Uploads` MODIFY `Id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=0;
";
$result = mysqli_query($conn, $command) or die(mysqli_error($conn));
I think, that code is right (but obviously not). When I run it, SQL throws an error:
You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'IF OBJECT_ID(db.Users) IS NOT NULL DROP TABLE db.User' at line 1**.
This means that it don’t have a problem with connection to SQL database.
I tried instead of IF OBJECT_ID use IF NOT EXISTS, but it doesn't works too. Can anybody tell me if multi-line SQL command is this problem or if it is something else?
Note: I use 5.5.37 version of MariaDB (if it helps)
IF is not a valid SQL statement in MySQL / MariaDB.
The IF OBJECT_ID(...) statement in the question appears to be a Transact-SQL (Microsoft SQL Server) construct.
The equivalent functionality in MySQL would be achieved with
DROP TABLE IF EXISTS foo.mytable ;
(I expect this would work in MariaDB 5.5, but I haven't verified.)
Note that if the table doesn't exist, the execution of the statement will raise a warning. (A warning message, not an error message.)
The mysqli_query function runs a single statement. To run multiple statements, we can use mysqli_multi_query function, documented here:
http://php.net/manual/en/mysqli.multi-query.php
As far as concerns, OBJECT_ID does not exist in mysql, only in mssql. Searching for OBJECT_ID mysql 8.0 reference manual does not retun anything meaningful. Even if it existed, your syntax for IF block does not look good : you want IF...THEN...END.
To fix the error, you can replace this :
IF OBJECT_ID(`".$database.".Users`) IS NOT NULL
DROP TABLE ".$database.".Users;
IF OBJECT_ID(`".$database.".Uploads`) IS NOT NULL
DROP TABLE ".$database.".Uploads;
With :
DROP TABLE IF EXISTS ".$database.".Users;
DROP TABLE IF EXISTS ".$database.".Uploads;
never used OBJECT_ID but what you want seem to be easily doable with
"drop table if exists users;"

how do I give out incrementing keys to client side from php and mysql ?

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.

Insert or Update with prepared statements in MySQL

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";

INSERT INTO and primary keys, autoincrement fields, and default values

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.

Categories