CREATE TABLE IF NOT EXISTS `$id` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`start` varchar(10) NOT NULL,
`end` varchar(10) NOT NULL,
`date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=45 ;
INSERT INTO `$id`(`start`, `end`) VALUES ('0','0')
I have been trying to figure out how I can bind these two Mysql(requests(?)) into one with no success. Basically I want it to work so when I create the table it should also add the values 0 and 0 to "start" and "end" rows. But I still want the "Create table if not exists" to be in effect for the INSERT INTO. So if the table exist don't INSERT either.
You could do that with following single statement:
CREATE TABLE IF NOT EXISTS `$id` (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
`start` VARCHAR(10) NOT NULL,
`end` VARCHAR(10) NOT NULL,
`date` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB
SELECT '0' AS `start`, '0' AS `end`;
You use the CREATE TABLE ... SELECT syntax with selecting not from a table, but constant values and get the autoincrement value and the current_timestamp by default.
as of MySQL 5.5.6 or newer, see following excerpt from the manual, CREATE TABLE ... SELECT:
As of MySQL 5.5.6, handling of CREATE TABLE IF NOT EXISTS ... SELECT
statements was changed for the case that the destination table already
exists. This change also involves a change in MySQL 5.1 beginning with
5.1.51.
Previously, for CREATE TABLE IF NOT EXISTS ... SELECT, MySQL produced
a warning that the table exists, but inserted the rows and wrote the
statement to the binary log anyway. By contrast, CREATE TABLE ...
SELECT (without IF NOT EXISTS) failed with an error, but MySQL
inserted no rows and did not write the statement to the binary log.
MySQL now handles both statements the same way when the destination
table exists, in that neither statement inserts rows or is written to
the binary log. The difference between them is that MySQL produces a
warning when IF NOT EXISTS is present and an error when it is not.
This change means that, for the preceding example, the CREATE TABLE IF
NOT EXISTS ... SELECT statement inserts nothing into the destination
table as of MySQL 5.5.6.
Related
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;"
I've a table folio with timestamp set to auto update.
CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
PDO statement in PHP is not causing the timestamp to update.
$statement = $this->connection->prepare("
INSERT INTO folio(publication, productId)
VALUES(:publication, :productId)
ON DUPLICATE KEY UPDATE
id=LAST_INSERT_ID(id), publication=:publication, productId=:productId");
following manual approach works but is not desirable.
$statement = $this->connection->prepare(
"INSERT INTO folio(publication, productId)
VALUES(:publication, :productId)
ON DUPLICATE KEY UPDATE
id=LAST_INSERT_ID(id), publication=:publication, productId=:productId, timestamp=NOW()");
Update: Here's my folio table structure
CREATE TABLE `folio` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`publication` varchar(255) DEFAULT NULL,
`productId` varchar(255) DEFAULT NULL,
`timestamp` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `unique_folio` (`publication`,`productId`)
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8;
Update 2: Table structure after setting timestamp to not null
CREATE TABLE `folio` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`publication` varchar(255) DEFAULT NULL,
`productId` varchar(255) DEFAULT NULL,
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `unique_folio` (`publication`,`productId`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
As far as I can see, the problem with your queries might be because you made timestamp field nullable
`timestamp` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
Try making it NOT NULL - since you have valid default value for it, MySQL won't complain you have not provided the value in the query:
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
Also, try renaming timestamp field to something more sane, e.g.:
`changed_timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
Also, as mentioned in my comments - you don't need to provide all fields in ON DUPLICATE KEY section, but only data fields:
INSERT INTO folio(publication, productId)
VALUES(:publication, :productId)
ON DUPLICATE KEY UPDATE
publication=:publication,
productId=:productId
It is because if MySQL detects you have a duplicate key condition, it won't insert new row, but update the existing one, therefore id column must be left intact.
UPDATE
Seems that not updating the timestamp column is a documented behavior - MySQL manual for TIMESTAMP columns
Citing the needed paragraph:
If the column is auto-updated, it is automatically updated to the current timestamp when the value of any other column in the row is changed from its current value. The column remains unchanged if all other columns are set to their current values. To prevent the column from updating when other columns change, explicitly set it to its current value. To update the column even when other columns do not change, explicitly set it to the value it should have (for example, set it to CURRENT_TIMESTAMP).
So, you are meeting all conditions :) - when you insert the record the timestamp should be populated correctly.
But when you provide the duplicate values on order to update the timestamp, MySQL sees you set the values that already exist in the row (otherwise it wouldn't be duplicate), therefore it does not update the timestamp column.
So, the solution is straightforward and already found by you - update the timestamp column explicitly whenever you provide the duplicate values, e.g.:
INSERT INTO folio(publication, productId)
VALUES(:publication, :productId)
ON DUPLICATE KEY UPDATE
`timestamp` = NOW()
Anyway, making timestamp NOT NULL won't hurt.
If the new INSERT values are the same as the old values in the duplicate row then apparently MySQL does not perform the UPDATE, therefore the ON UPDATE CURRENT_TIMESTAMP is not fired. :(
So, as an awkward workaround, you can add a dummy field to your table, forcing the UPDATE to occur (in the case of a duplicate id):
$statement = $this->connection->prepare("
INSERT INTO folio(publication, productId)
VALUES(:publication, :productId)
ON DUPLICATE KEY UPDATE
id=LAST_INSERT_ID(id), publication=:publication, productId=:productId,
dummy = NOT dummy
");
...as suggested in the User Comments here: http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html
it's just
insert into your_table (a, b) values (?, ?) on duplicate key update created = current_timestamp
For better or worse, MySQL does not , in any way, default-update timestamps in the case of insert-uniquely type calls.
it does not matter which of the three, insert-on-dupe, replace, insert-ignore you are using
it does not make any difference whatsoever which settings or qualities you use on the fields, table or anything else
It just has to be done manually by adding created = current_timestamp on the end.
Unfortunately that's it!
I am trying to create mysql table in PhpMyAdmin in Hostgator server with the following information but it is showing error
Error : #1067 - Invalid default value for 'CreatedDate'
Table
CREATE TABLE `tbl_sample` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`Domain` varchar(100) DEFAULT NULL,
`ClickUrl` varchar(600) DEFAULT NULL,
`CreatedDate` datetime NULL DEFAULT now(),
`ModifyDate` timestamp NULL DEFAULT NULL on update now(),
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
The purpose of table is I need to enter only 'Domain' and 'ClickUrl' data using insert command remaining Id(autoincrement),CreatedDate(current date when inserting row),ModifyDate(when update the row) will automatically insert.
The above table is executed successfully in mysql environment in my local system but it is not executing in the mysql environment in hostgator
Check this link]1
Problem with creating Two column with timestamps. have to use trigger to get it done.
I want to know if it's possible to INSERT records from a SELECT statement from a source table into a destination table, get the INSERT ID's and UPDATE a field on all the corresponding records from source table.
Take for example, the destination table 'payments':
CREATE TABLE `payments` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`txid` TEXT NULL,
`amount` DECIMAL(16,8) NOT NULL DEFAULT '0.00000000',
`worker` INT(10) UNSIGNED NOT NULL,
PRIMARY KEY (`id`)
)
The source table 'log':
CREATE TABLE `log` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`solution` VARCHAR(80) NOT NULL,
`worker` INT(11) NOT NULL,
`amount` DECIMAL(16,8) NOT NULL DEFAULT '0.00000000',
`pstatus` VARCHAR(50) NOT NULL DEFAULT 'pending',
`payment_id` INT(10) UNSIGNED NULL DEFAULT NULL,
PRIMARY KEY (`id`)
)
The "log" table contains multiple "micro-payments" for a completed task. The purpose of the "payments" table is to consolidate the micro-payments into one larger payment:
INSERT INTO payments p (amount, worker)
SELECT SUM(l.amount) AS total, l.worker FROM log l
WHERE l.pstatus = "ready"
AND l.payment_id IS NULL
AND l.amount > 0
GROUP BY l.worker
I'm not sure if clear from the code above, but I would like the field "payment_id" to be given the value of the insert id so that it's possible to trace back the micro-payment to the larger consolidated payment.
I could do it all client side (PHP), but I was wondering if there was some magical SQL query that would do it for me? Or maybe I am going about it all wrong.
You can use mysql_insert_id() to get the id the inserted record.
See mysql_insert_id()
But the above function is deprecated.
If you're using PDO, use PDO::lastInsertId.
If you're using Mysqli, use mysqli::$insert_id.
Well, the linking column between the tables is the column worker. After you inserted your values, just do
UPDATE log l
INNER JOIN payments p ON l.worker = p.worker
SET l.payment_id = p.id;
and that's it. Or did I get the question wrong? Note, that the columns differ in the attribute signed/unsigned. You might want to change that.
I think you should use ORM in php as follows:
Look into Doctrine.
Doctrine 1.2 implements Active Record. Doctrine 2+ is a DataMapper ORM.
Also, check out Xyster. It's based on the Data Mapper pattern.
Also, take a look at DataMapper vs. Active Record.
I want to do the following:
Select multiple rows on an INNER JOIN between two tables.
Using the primary keys of the returned rows, either:
Update those rows, or
Insert rows into a different table with the returned primary key as a foreign key.
In PHP, echo the results of step #1 out, ideally with results of #2 included (to be consumed by a client).
I've written the join, but not much else. I tried using a user-defined variable to store the primary keys from step #1 to use in step #2, but as I understand it user-defined variables are single-valued, and my SELECT can return multiple rows. Is there a way to do this in a single MySQL transaction? If not, is there a way to do this with some modicum of efficiency?
Update: Here are the schemas of the tables I'm concerned with (names changed, 'natch):
CREATE TABLE IF NOT EXISTS `widgets` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`author` varchar(75) COLLATE utf8_unicode_ci NOT NULL,
`text` varchar(500) COLLATE utf8_unicode_ci NOT NULL,
`created` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`updated` timestamp
NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
);
CREATE TABLE IF NOT EXISTS `downloads` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`widget_id` int(11) unsigned NOT NULL,
`lat` float NOT NULL,
`lon` float NOT NULL,
`date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
);
I'm currently doing a join to get all widgets paired with their downloads. Assuming $author and $batchSize are php vars:
SELECT w.id, w.author, w.text, w.created, d.lat, d.lon, d.date
FROM widgets AS w
INNER JOIN downloads AS d
ON w.id = d.widget_id
WHERE w.author NOT LIKE '$author'
ORDER BY w.updated ASC
LIMIT $batchSize;
Ideally my query would get a bunch of widgets, update their updated field OR insert a new download referencing that widget (I'd love to see answers for both approaches, haven't decided on one yet), and then allow the joined widgets and downloads to be echoed. Bonus points if the new inserted download or updated widgets are included in the echo.
Since you asked if you can do this in a single Mysql transaction I'll mention cursors. Cursors will allow you to do a select and loop through each row and do the insert or anything else you want all within the db. So you could create a stored procedure that does all the logic behind the scenes that you can call via php.
Based on your update I wanted to mention that you can have the stored procedure return the new recordset or an I'd, anything you want. For more info on creating stored procedures that return a recordset with php you can check out this post: http://www.joeyrivera.com/2009/using-mysql-stored-procedure-inout-and-recordset-w-php/