How can I insert or update if a value is different? - mysql

I'm trying to write an SQL query that will set a value to 1 when it updates another column.
Specifically, I want to set my is_patch_file to 1 if the corresponding hash column is changed. If the hash column is NOT changed, it should keep whatever the currently stored is_patch_file value is.
Is this possible?
Table Structure
DROP TABLE IF EXISTS `program_files`;
CREATE TABLE `program_files` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`folder_id` int(10) unsigned NOT NULL,
`name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
`path` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
`hash` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
`enabled` tinyint(1) NOT NULL DEFAULT '1',
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
`is_patch_file` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `unique_file` (`folder_id`,`name`,`path`,`hash`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
SQL Queries
INSERT INTO program_files (folder_id, name, path, hash, is_patch_file, enabled, created_at, updated_at) VALUES (3, 'TestName', 'TestPath', 'TestHash', 0, 1, NOW(), NOW()) ON DUPLICATE KEY UPDATE
is_patch_file=1, #Is Patch file should ONLY be 1 if the hash is different from the original hash...otherwise keep our current value how do I do this?
hash=VALUES(hash),
updated_at=VALUES(updated_at);
INSERT INTO program_files (folder_id, name, path, hash, is_patch_file, enabled, created_at, updated_at) VALUES (3, 'TestName', 'TestPath', 'TestHash2', 0, 1, NOW(), NOW()) ON DUPLICATE KEY UPDATE
is_patch_file=1, #Is Patch file should ONLY be 1 if the hash is different from the original hash...otherwise keep our current value how do I do this?
hash=VALUES(hash),
updated_at=VALUES(updated_at);

You can compare hash to VALUES(hash) before it gets updated, and use that when setting is_patch_file.
ON DUPLICATE KEY UPDATE
is_patch_file = hash != VALUES(hash),
hash = VALUES(hash),
updated_at = VALUES(updated_at)

Related

Get data of table with some data from other table

I have a simple table visitor and another table visitor_tokens.
SQL creation script of visitor:
CREATE TABLE `visitor` (
`id` int(7) UNSIGNED NOT NULL,
`phone` varchar(15) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
ALTER TABLE `visitor`
ADD PRIMARY KEY (`id`),
ADD UNIQUE KEY `phone_index` (`phone`);
ALTER TABLE `visitor`
MODIFY `id` int UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=1;
INSERT INTO `visitor` (`phone`) VALUES
('111111111');
SQL creation script of visitor_tokens:
CREATE TABLE `visitor_tokens` (
`id` int(7) UNSIGNED NOT NULL,
`visitor` int(7) UNSIGNED NOT NULL,
`token` varchar(100) COLLATE utf8mb4_general_ci NOT NULL,
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
ALTER TABLE `visitor_tokens`
ADD PRIMARY KEY (`id`);
ALTER TABLE `visitor_tokens`
MODIFY `id` int UNSIGNED NOT NULL AUTO_INCREMENT;
INSERT INTO `visitor_tokens` (`visitor`, `token`) VALUES
(1, 'abc_token'),
(1, 'xyz_token');
I want to get some data of visitor by id:
I want to get the phone number (phone column) and the visitor tokens (visitor_tokens.token). All - according to given id.
My current SQL script is: SELECT visitor.phone, visitor_tokens.token FROM visitor JOIN visitor_tokens ON visitor_tokens.visitor=visitor.id WHERE id=1. This gives me only the phone and the first token: abc. But I also want to get the tokens of the visitor from the second table. To get something like [abc_token, xyz_token]. How can I do it?
So this is my solution (also recommend on reading the main comments):
SELECT visitor.phone, GROUP_CONCAT(visitor_tokens.token) AS tokens FROM visitor LEFT JOIN visitor_tokens ON visitor_tokens.visitor=visitor.id WHERE visitor.id=1 LIMIT 1;
It returns result regardless of missing visitor tokens (LEFT JOIN), and also if there are tokens - it returns the tokens separated by comma in one row.

Mysql Insert with milisecond

We're building chat system for our project. When user create chat group or send message to a group, we have to take user event time with milisecond. The sample database is below.
CREATE TABLE `chats` (
`id` int(11) NOT NULL,
`chat_id` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
`status` float NOT NULL DEFAULT '1',
`chat_user` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
`user_type` varchar(11) COLLATE utf8_unicode_ci NOT NULL DEFAULT 'users',
`last_seen` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
`delete_date` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
`update_date` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
`create_date` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
The problem is, when we insert new data into table, mysql takes current time as "0000-00-00 00:00:00.000". All zero, not even date. But if we edit that data after insert, current_timestamp works perfect.
From the MySQL documentation:
When inserting a new row, the default value for a column with an expression default can be inserted either by omitting the column name or by specifying the column as DEFAULT (just as for columns with literal defaults):
So, your options here for getting the default value to kick in are either doing an insert which does not mention the column at all, or using the placeholder DEFAULT. Both of the following should generate the same result:
INSERT INTO chats (id, chat_id, status, chat_user, user_type, last_seen, delete_date,
update_date, create_date)
VALUES
(1, 1, 1.0, 'tim', 'admin', DEFAULT, DEFAULT, DEFAULT, DEFAULT);
and
INSERT INTO chats (id, chat_id, status, chat_user, user_type)
VALUES
(1, 1, 1.0, 'tim', 'admin');
$timestamp=round(microtime(true) * 1000);
store $timestamp variable value in your database column. This is utc based timestamp and you can easily convert it into local time as well.

How to set a default constant value for timestamp columns?

I have a table with a nullable timestamp field (enddate)
CREATE TABLE `fee` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`type` varchar(50) NOT NULL DEFAULT 'FIXED',
`name` varchar(100) NOT NULL,
`description` varchar(255) DEFAULT NULL,
`startdate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`enddate` datetime NOT NULL DEFAULT '2038-01-18 22:00:00',
PRIMARY KEY (`id`),
) ENGINE=InnoDB;
I run an insert, passing a null to startdate and enddate, expecting that it would use my default values. So running:
INSERT INTO `fee` (`type`, `name`, `description`, `startdate`, `enddate`)
VALUES
('FIXED', 'Delivery fee', NULL, NULL, NULL);
Would insert:
27, FIXED, Delivery fee, NULL, NOW(), '2038-01-18 22:00:00'
But it inserts:
27, FIXED, Delivery fee, NULL, NOW(), NOW()
I tried this in mysql 5.5, 5.6 and 5.7, based on their documentation:
Use of DEFAULT CURRENT_TIMESTAMP and ON UPDATE CURRENT_TIMESTAMP is specific to TIMESTAMP. The DEFAULT clause also can be used to specify a constant (nonautomatic) default value; for example, DEFAULT 0 or DEFAULT '2000-01-01 00:00:00'.
Question is, what am I doing wrong?
When you set default value for any field in table, you only should pass the value when you actually wants to insert something else rather then default value. You were setting it to null with your query but IN your CREATE query
`enddate` datetime NOT NULL DEFAULT '2038-01-18 22:00:00'
you have set it as it should be 'NOT NULL'.

Data is not inserted in mysql

I have the following table:
(Yes, the table names are silly... I'm just messing about)
CREATE TABLE `habitat`.`habit` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`content` text NOT NULL,
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`deleted` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`user_id` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8
When I try to do the following sql statement, only 0 shows up in content:
INSERT into habit
(content, user_id)
VALUES (content = 'this is some habit', user_id = 2)
Basically you do not need to include the "columnName = value" in the VALUES portion of an insert statement. It should look like this.
INSERT INTO habit (
content,
user_id)
VALUES (
'this is some habit',
2)

MySQL - Cannot insert NULL value in column, but I have a default value specified?

I have a table in MySQL that have a few columns that have default values specified, but when I try to insert a row, (not specifying values for those default columns), it throws an error saying I cannot insert NULL values.
Here is the table example;
CREATE TABLE `users` (
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`UniqueName` varchar(120) NOT NULL,
`Password` varchar(1000) NOT NULL,
`PublicFlag` tinyint(1) NOT NULL,
`NoTimesLoggedIn` int(10) unsigned NOT NULL DEFAULT '0',
`DateTimeLastLogin` timestamp NOT NULL DEFAULT '1971-01-01 00:00:00',
`UserStatusTypeId` int(10) unsigned NOT NULL,
`Private` tinyint(1) NOT NULL DEFAULT '0',
`SiteName` varchar(255) NOT NULL,
`CountryId` int(10) NOT NULL DEFAULT '0',
`TimeZoneId` varchar(255) NOT NULL DEFAULT 'UTC',
`CultureInfoId` int(10) unsigned NOT NULL DEFAULT '0',
`DateCreated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`UserCreated` int(10) unsigned NOT NULL,
`LastUpdatedBy` int(10) unsigned NOT NULL,
`DateLastUpdated` datetime DEFAULT NULL,
PRIMARY KEY (`Id`),
UNIQUE KEY `UniqueName_UNIQUE` (`UniqueName`),
KEY `Index 3` (`SiteName`)
)
It complains about TimeZoneId, and when I populate TimeZoneId, it complains about CultureInforId.
I am using MySQL Version: 5.1.43-community
Here is the insert query I am trying to insert, grabbed from NHibernate Profiler:
INSERT INTO Users
(UniqueName,
Password,
PublicFlag,
NoTimesLoggedIn,
DateTimeLastLogin,
SiteName,
TimeZoneId,
DateCreated,
DateLastUpdated,
Private,
CountryId,
CultureInfoId,
UserCreated,
LastUpdatedBy,
UserStatusTypeId)
VALUES ('zma#zm.com','u1uhbQviLp89P9b3EnuN/Prvo3A4KVSiUa0=',1,
0,'1/01/1971 12:00:00 AM','V9O1T80Q6D',NULL,'2/08/2010 2:13:44 AM',
'2/08/2010 2:13:44 AM',0, NULL, NULL, 4, 4,31)
Use the DEFAULT keyword instead:
INSERT INTO users (TimeZoneId) VALUES (DEFAULT);
Do not insert NULL values. I'm assuming you were trying this syntax:
INSERT INTO users VALUES (null, 'Jones', 'yarg', 1, null, null, null);
Instead, use this syntax:
INSERT INTO users SET UniqueName='Jones', Password='yarg';
For more info, see the MySQL docs on INSERT.
You have "NOT NULL" set on fields that you are trying to INSERT NULL on.
eg.
CountryId,
CultureInfoId,
TimeZoneId
execute the following:
ALTER TABLE `users` MODIFY `CountryId` int(10) DEFAULT '0' NULL;
ALTER TABLE `users` MODIFY `CultureInfoId` int(10) unsigned DEFAULT '0' NULL;
ALTER TABLE `users` MODIFY `TimeZoneId` varchar(255) DEFAULT 'UTC' NULL;
EDIT: Didn't realize he wanted the default value instead of NULL on "null" insert. Basically as already has been suggested use the DEFAULT keyword in place of NULL on the values.
OR leave the NULL fields and values out altogether and mysql will use the defined defaults eg.
INSERT INTO Users
(UniqueName,
Password,
PublicFlag,
NoTimesLoggedIn,
DateTimeLastLogin,
SiteName,
DateCreated,
DateLastUpdated,
Private,
UserCreated,
LastUpdatedBy,
UserStatusTypeId)
VALUES ('zma#zm.com','u1uhbQviLp89P9b3EnuN/Prvo3A4KVSiUa0=',1,
0,'1/01/1971 12:00:00 AM','V9O1T80Q6D','2/08/2010 2:13:44 AM',
'2/08/2010 2:13:44 AM',0, 4, 4,31)
The documentation says that from version 5.6 you need to access fields by default.
I've read this post about this trouble
I've fixed it this way:
mysql> show global variables like 'explicit_defaults_for_timestamp';
And if your field has ON value change to OFF
mysql> set global explicit_defaults_for_timestamp=0;
That's all.
As an alternative to using the DEFAULT keyword you can also just not specify values for the fields which you want to have default values. For instance if you just removed TimeZoneId, CountryId and CultureInfoId from your query entirely those columns will receive the default values automatically:
INSERT INTO Users
(UniqueName,
Password,
PublicFlag,
NoTimesLoggedIn,
DateTimeLastLogin,
SiteName,
DateCreated,
DateLastUpdated,
Private,
UserCreated,
LastUpdatedBy,
UserStatusTypeId)
VALUES
('zma#zm.com','u1uhbQviLp89P9b3EnuN/Prvo3A4KVSiUa0=',1,0,
'1/01/1971 12:00:00 AM','V9O1T80Q6D','2/08/2010 2:13:44 AM',
'2/08/2010 2:13:44 AM',0,4,4,31)
I'm not sure how that would work in the context of NHibernate however as that part of the question wasn't quite as well explained.
TimeZoneIdvarchar(255) NOT NULL DEFAULT 'UTC',
CultureInfoId` int(10) unsigned NOT NULL DEFAULT '0',
For this fields you have set constraints as "Not Null" and hence values inserted can't be null and hence either alter the table structure or just not specify values for the fields which you want to have default values.