MySQL: Check constraint with Date - mysql

I am using MySQL and here is a simple query set:
create table dcheck (
fdate date,
sdate date,
check (fdate <= sdate)
);
insert into dcheck values ('2006-12-12','2003-12-12');
insert into dcheck values ('2003-12-12', '2006-12-12');
Here I expect the first insert statement to fail. But surprisingly, both the queries passes and two rows are there in the table.
Can anyone please explain why?
Thanks

MySQL doesn't implement CHECK constraints. From the latest (5.6) fine manual:
The CHECK clause is parsed but ignored by all storage engines.
So the syntax is parsed for compatibility other other SQLs but the checking is not implemented.
You could fake your CHECK constraint with BEFORE INSERT and BEFORE UPDATE triggers that threw an exception if the desired condition was not met.

The CHECK clause is parsed but ignored by all storage engines.
http://dev.mysql.com/doc/refman/5.1/en/create-table.html

CHECK constraints are now supported since MySQL 8.0.16

Related

HSQLDB: REPLACE INTO

From:
HyperSQL User Guide
HyperSQL Database Engine 2.4.0
Chapter 12. Compatibility With Other DBMS :
HyperSQL supports and translates INSERT IGNORE, REPLACE and ON
DUPLICATE KEY UPDATE variations of INSERT into predictable and
error-free operations.
When INSERT IGNORE is used, if any of the inserted rows would violate
a PRIMARY KEY or UNIQUE constraint, that row is not inserted. The rest
of the rows are then inserted only if there is no other violation such
as long strings or type mismatch, otherwise the appropriate error is
returned.
When REPLACE or ON DUPLICATE KEY UPDATE is used, the rows that need
replacing or updating are updated with the given values. This works
exactly like an UPDATE statement for those rows. Referential
constraints and other integrity checks are enforced and update
triggers are activated. The row count returned is simply the total
number of rows inserted and updated.
However when I try
REPLACE INTO my_table (my_id, my_int) VALUES (1, 2);
I get
unexpected token: REPLACE required: INSERT
Why is that?
I suggest that you need to enable MySQL compatibility mode in order to get MySQL-specific commands like REPLACE to work. From Chapter 7 of the HSQL documentation:
In MySQL syntax compatibility mode, HyperSQL supports INSERT IGNORE, REPLACE and ON DUPLICATE KEY UPDATE variations of the INSERT statement.
The key point here is that it MySQL syntax compatibility mode needs to be turned on. Following the link to Chapter 12 which you posted in your question we find:
Use SET DATABASE SQL SYNTAX MYS TRUE or the equivalent URL property sql.syntax_mys=true to enable support for AUTO_INCREMENT and TEXT data types and several other types. These type definitions are translated into HyperSQL equivalents.
So the documentation is giving us two ways to enable MySQL compatibility mode. One we can execute directly from the HSQL console:
SET DATABASE SQL SYNTAX MYS TRUE
The other, probably the one to use for development purposes, is to add the following to the connection string:
sql.syntax_mys=true
Once you have MySQL compatibility mode enabled, REPLACE should work without error.

php mySQL check for unique value needed on Unique col?

is it necessary to check for Unique Value before insert it in to a database? if the unique_col is predefine to be Unique Keys.
for example
SELECT unique_col FROM table WHERE unique_col != unique_val
INSERT INTO table (unique_col) VALUE(:unique_value)
Is it necessary to check? That depends how you are handling the error.
In general, the database is going to do the check anyway, so an additional check on your part is redundant. If you do the check, another thread might insert the same value between your check and the insert, so you can still get an error (this is called a race condition).
So, don't do the check, but do check for the error.

Is there an engine for MySQL/MariaDB that enforces CHECK?

I know that InnoDB enforces foreign key. Is there a engine for MySQL/MariaDB that really implements CHECK?
Suppose I create a table with the following command:
create table a(t timestamp not null, check (t > '2014-05-01')) ENGINE=InnoDB;
and I try to insert a row that is suppose to be invalid:
insert into a(t) values('2014-01-01');
MySQL, using InnoDB, allow the insertion of that invalid row. I would like to use an engine that would not accept that insert. Is there an engine for that job?
CHECK constraint works as expected in MariaDB 10.2, which is currently beta.
https://jira.mariadb.org/browse/MDEV-7563
There is no such engine in MySQL. If you must check at the database level, your only option is to use triggers and validate the data there.
Maybe one day though:
http://bugs.mysql.com/bug.php?id=3464

SQL standard UPSERT call

I'm looking for a standard SQL "UPSERT" statement. A one call for insert and update if exists.
I'm looking for a working, efficient and cross platform call.
I've seen MERGE, UPSERT, REPLACE, INSERT .. ON DUPLICATE UPDATE but no statement meets the needs.
BTW I use MYSQL and HSQLDB for unitests. I understand that HSQLDB is limited and may not cover what I need, but I couldn't find a standard way even without it.
A statement that only MYSQL and HSQLDB will also be enough for now.
I've been looking around for a while and couldn't get an answer.
My table:
CREATE TABLE MY_TABLE (
MY_KEY varchar(50) NOT NULL ,
MY_VALUE varchar(50) DEFAULT NULL,
TIME_STAMP bigint NOT NULL,
PRIMARY KEY (MY_KEY)
);
Any idea?
The only solution that is supported by both MySQL and HSQLDB is to query the rows you intend to replace, and conditionally either INSERT or UPDATE. This means you have to write more application code to compensate for the differences between RDBMS implementations.
START TRANSACTION.
SELECT ... FOR UPDATE.
If the SELECT finds rows, then UPDATE.
Else, INSERT.
COMMIT.
MySQL doesn't support the ANSI SQL MERGE statement. It supports REPLACE and INSERT...ON DUPLICATE KEY UPDATE. See my answer to "INSERT IGNORE" vs "INSERT ... ON DUPLICATE KEY UPDATE" for more on that.
Re comments: Yes, another approach is to just try the INSERT and see if it succeeds. Otherwise, do an UPDATE. If you attempt the INSERT and it hits a duplicate key, it'll generate an error, which turns into an exception in some client interfaces. The disadvantage of doing this in MySQL is that it generates a new auto-increment ID even if the INSERT fails. So you end up with gaps. I know gaps in auto-increment sequence are not ordinarily something to worry about, but I helped a customer last year who had gaps of 1000-1500 in between successful inserts because of this effect, and the result was that they exhausted the range of an INT in their primary key.
As #baraky says, one could instead attempt the UPDATE first, and if that affects zero rows, then do the INSERT instead. My comment on this strategy is that UPDATEing zero rows is not an exception -- you'll have to check for "number of rows affected" after the UPDATE to know whether it "succeeded" or not.
But querying the number of rows affected returns you to the original problem: you have to use different queries in MySQL versus HSQLDB.
HSQLDB:
CALL DIAGNOSTICS(ROW_COUNT);
MySQL:
SELECT ROW_COUNT();
The syntax for doing an upsert in a single command varies by RDBMS.
MySQLINSERT…ON DUPLICATE KEY UPDATE
HSQLDBMERGE
PostgresINSERT…ON CONFLICT…
See Wikipedia for more.
If you want a cross platform solution, then you'll need to use multiple commands. First check for the existing row, then conditionally insert or update as appropriate.

Enforcing unique columns

If a column is made unique in a database table structure, is there any need to do a check to see if a new value to be inserted already exists in the table via script? Or would it be fine just to insert values letting the DBMS filter non-new values?
When you will try to insert a duplicate value in a unique column, your insert query will fail. So it might be a good idea to make sure you are checking to see if your insert queries went well or not. Althought regardless of the situation you should always check if your insert query went through or not :)
You should always validate your data before inserting it on the database. That being said, what will happen if you try to insert a non-unique value on a unique defined column is an SQLexception.
In order to validate this before insertion, you could for example do a
select 1
from mytable_with_unique_column
where my_unique_column = myNewValue
If the query returns anything, then simply do not try to insert as that will throw an SQLException.
Verification of unique constraint is definitely an overkill.
When you put unique constraint on your column, an implicit index is created for this column. Thus, DBMS can (and will) verify your data much faster. Unfortunately, when you try to insert duplicate value into your column, you will get constraint violation exception you have to deal with (but you have to deal with such error while using script verification either).
Good luck.
You can combine the insert statement and validation select into one statement:
insert into mytable_with_unique_column (...) values (...)
where not exists
(
select 1
from mytable_with_unique_column
where my_unique_column = myNewValue
)
This will only insert a new row if there isn't already a row with the given unique value.