MySQL: Forbid empty string on insert when wrong enum value specified - mysql

Is there a way to forbid empty string when wrong enum value is specified? whithout setting sql in "strict" or "traditional" mode
CREATE TABLE test (
foo enum('aaa','bbb') NOT NULL
);
INSERT INTO test VALUES('asd');

You could write a CHECK constraint (requires MySQL 8.0):
mysql> set sql_mode='';
mysql> alter table test add check (foo != '');
mysql> INSERT INTO test VALUES('asd');
ERROR 3819 (HY000): Check constraint 'test_chk_1' is violated.
Or you could do something similar in a trigger.
But I recommend you just enable strict mode.

You can write your INSERT statement with a SELECT that will allow you to utilize a WHERE clause:
INSERT INTO test (foo) SELECT 'aaa' WHERE 'aaa' IN ('aaa', 'bbb');
Query OK, 1 row affected (0.05 sec)
Records: 1 Duplicates: 0 Warnings: 0
INSERT INTO test (foo) SELECT 'ccc' WHERE 'ccc' IN ('aaa', 'bbb');
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0

Related

I can't update my table in MySQL. Rows matched: 0 Changed: 0 Warnings: 0

I have never had problems like this and I can't find the problem.
https://i.stack.imgur.com/RJBCK.png
CREATE TABLE setting_cube(i INT, subject VARCHAR(30));
Query OK, 0 rows affected (0.03 sec)
UPDATE setting_cube SET i='1', subject='#uno';
Query OK, 0 rows affected (0.01 sec)
Rows matched: 0 Changed: 0 Warnings: 0
and if I try:
SELECT * FROM setting_cube;
Empty set (0.00 sec)
even though I have updated the table...
What am I doing wrong? thank youuuu!!!
The table is empty. You should insert some rows before updating them in the second step:
INSERT INTO setting_cube VALUES (1, 'first row');
Create TABLE setting_cube(i INT, subject VARCHAR(30));
----First you need to insert some x date
insert into setting_cube values (1 ,'Test')
---Now You can Update table
update setting_cube set i = 1 , subject = '#uno'
select * from setting_cube

How to simulate long running alter query on MySQL

I have a system and I want to test it which executes Alter queries. I'm looking for a way to simulate a long-running Alter query that I can test "panic", "resource usage", "concurrency", ... when it's running.
Is there any way that exists I can simulate a long-running Alter query?
I'm using gh-ost for alter execution.
Here's what I do when I want to test a long-running ALTER TABLE:
Create a table.
Fill it with a few million rows of random data, until it's large enough that ALTER TABLE takes a few minutes. How many rows are required depends on the speed of your computer.
Run ALTER TABLE on it.
I have not found a better solution, and I've been using MySQL since 2001.
Here's a trick for filling lots of rows without needing a client app or script:
mysql> create table mytable (id int auto_increment primary key, t text);
Query OK, 0 rows affected (0.05 sec)
mysql> insert into mytable (t) select repeat(sha1(rand()), 255) from dual;
Query OK, 1 row affected (0.02 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> insert into mytable (t) select repeat(sha1(rand()), 255) from mytable;
Query OK, 1 row affected (0.03 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> insert into mytable (t) select repeat(sha1(rand()), 255) from mytable;
Query OK, 2 rows affected (0.02 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> insert into mytable (t) select repeat(sha1(rand()), 255) from mytable;
Query OK, 4 rows affected (0.03 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql> insert into mytable (t) select repeat(sha1(rand()), 255) from mytable;
Query OK, 8 rows affected (0.03 sec)
Records: 8 Duplicates: 0 Warnings: 0
mysql> insert into mytable (t) select repeat(sha1(rand()), 255) from mytable;
Query OK, 16 rows affected (0.03 sec)
Records: 16 Duplicates: 0 Warnings: 0
Now I have 32 rows (16+8+4+2+1+1). I can continue the same query as many times as I want, which doubles the size of the table each time. It doesn't take long before I have a table several gigabytes
in size.

Can I make mysql table columns case insensitive?

I am new to mysql (and sql in general) and am trying to see if I can make data inserted into a column in a table case insensitive.
I am storing data like state names, city names, etc. So I want to have a unique constraint on these types of data and on top of that make them case insensitive so that I can rely on the uniqueness constraint.
Does mysql support a case-insensitive option on either the column during table creation or alternatively when setting the uniqueness constraint on the column? What is the usual way to deal with such issues? I would appreciate any alternate ideas/suggestions to deal with this.
EDIT: As suggested, does COLLATE I think only applies to queries on the inserted data. But to really take advantage of the uniqueness contraint, I want to have a case insensitivity restriction on INSERT. For e.g. I want mysql to not allow insertions of California and california and cALifornia as they should be the same. But if I understand the uniqueness constraint prooperly, having it on the StateName will still allow the above four inserts.
By default, MySQL is case-insensitive.
CREATE TABLE test
(
name VARCHAR(20),
UNIQUE(name)
);
mysql> INSERT INTO test VALUES('California');
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO test VALUES('california');
ERROR 1062 (23000): Duplicate entry 'california' for key 'name'
mysql> INSERT INTO test VALUES('cAlifornia');
ERROR 1062 (23000): Duplicate entry 'cAlifornia' for key 'name'
mysql> INSERT INTO test VALUES('cALifornia');
ERROR 1062 (23000): Duplicate entry 'cALifornia' for key 'name'
mysql> SELECT * FROM test;
+------------+
| name |
+------------+
| California |
+------------+
1 row in set (0.00 sec)
Use BINARY when you need case-sensitivity
To make case-sensitive in MySQL, BINARY keyword is used as follows
mysql> CREATE TABLE test
-> (
-> name varchar(20) BINARY,
-> UNIQUE(name)
-> );
Query OK, 0 rows affected (0.00 sec)
mysql>
mysql> INSERT INTO test VALUES('California');
Query OK, 1 row affected (0.00 sec)
mysql>
mysql> INSERT INTO test VALUES('california');
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO test VALUES('cAlifornia');
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO test VALUES('cALifornia');
Query OK, 1 row affected (0.00 sec)
mysql>
mysql> SELECT * FROM test;
+------------+
| name |
+------------+
| California |
| cALifornia |
| cAlifornia |
| california |
+------------+
4 rows in set (0.00 sec)
You can use COLLATE operator: http://dev.mysql.com/doc/refman/5.0/en/case-sensitivity.html

Why doesn't this IF NOT EXISTS statement work?

I'm trying to write a query which will INSERT a random value between 0 to 9999 INTO a table, whereas this random value is yet to exist there.
However, nothing I wrote works. It seems like a WHERE clause doesn't work with INSERT, and my SQL server fails to execute an IF NOT EXISTS query. Is it incorrect, I wonder?
What should I do? Is there a solution to my problem?
(I'm using MySQL)
SET #rand = ROUND(RAND() * 9999);
IF NOT EXISTS (SELECT `num` FROM `nums` WHERE `num` = #rand)
INSERT INTO `nums` (`num`) VALUES (#rand);
You can do it like here: MySQL: Insert record if not exists in table
INSERT INTO `nums` (`num`)
SELECT *
FROM
(SELECT #rand) AS q
WHERE NOT EXISTS
(SELECT `num`
FROM `nums`
WHERE `num` = #rand);
Try it using a stored procedure like this:
CREATE PROCEDURE my_sp()
BEGIN
SET #rand = ROUND(RAND() * 9999);
IF NOT EXISTS (SELECT `num` FROM `nums` WHERE `num` = #rand) THEN
INSERT INTO `nums` (`num`) VALUES (#rand);
END IF;
END
Using statements like IF belongs inside a block of code like a stored procedure. You won't be able to execute it just on the mysql prompt.
If you just want to insert the a random value that wasn't there before you can also do it by
mysql> create table nums(num int, unique key(num));
Query OK, 0 rows affected (0.05 sec)
mysql> insert ignore into nums >select round(rand()*9999);>
Query OK, 1 row affected (0.01 >sec)>
Records: 1 Duplicates: 0 Warn>ings>: 0>
mysql> insert ignore into nums select round(rand()*9999);
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> insert ignore into nums select round(rand()*9999);
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> insert ignore into nums select round(rand()*9999);
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> select * from nums;
+------+
| num |
+------+
| 5268 |
| 9075 |
| 9114 |
| 9768 |
+------+
4 rows in set (0.00 sec)
mysql>
With insert ignore, it won't insert a row if it already exists.

Trigger Syntax Error in MySQL on IF/THEN (ERROR 1064)

I have an error while executing this query:
CREATE TRIGGER insert_Topics
BEFORE INSERT
ON Topics
FOR EACH ROW
BEGIN
IF (SELECT COUNT(*) FROM Subjects WHERE ID=new.SubjectID)=0
THEN
INSERT error_msg VALUES ('Foreign Key Constraint Violated!');
END IF;
END;
delimiter ;
The error says:
1064 - You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use
near '' at line 8
and it points to the word THEN
Any help? Thanks in advance.
Both
CREATE TRIGGER insert_Topics
BEFORE INSERT
ON Topics
FOR EACH ROW
BEGIN
IF NOT EXISTS(SELECT 1 FROM Subjects WHERE ID=NEW.SubjectID LIMIT 1) THEN
INSERT INTO error_msg VALUES ('Foreign Key Constraint Violated!');
END IF;
END;
and
CREATE TRIGGER insert_Topics
BEFORE INSERT
ON Topics
FOR EACH ROW
BEGIN
IF (SELECT 1 FROM Subjects WHERE ID=NEW.SubjectID LIMIT 1) IS NULL THEN
INSERT INTO error_msg VALUES ('Foreign Key Constraint Violated!');
END IF;
END;
work for me, so your syntax problems probably lie elsewhere.
I know this is an old question, but I thought I'd share my thoughts over what I think the error was, in case anyone sees this in the future (feel free to community-edit if i've made any mistakes!).
The reason there were issues in the original question seems to be with the use of DELIMITER, and what it does, as explained here: What does DELIMITER // do in a Trigger?
In the given code:
INSERT error_msg VALUES ('Foreign Key Constraint Violated!');
END IF;
END;
delimiter ;
The resetting of delimiter with "delimiter ;" indicates that it changed previously to another delimiter, say:
DELIMITER //
--TRIGGER1
--TRIGGER2
--TRIGGERn
delimiter ; -- Aggravates me that this wasn't capitalised :P
The reason for the delimiter to be set to "//" (or others), is to allow multiple statements to be delimited, and what I'm thinking, is that the original author had other triggers above that trigger, and had changed the delimiter to something like "//", but had forgotten to change:
END IF;
END;
delimiter ;
To:
END IF;
END//
delimiter ;
Therefore, the reason why commenters weren't able to replicate, was because they had the correct delimiter set (";"), and as there was only one statement to delimit, didn't find any errors, as the author did.
See the following test code and results, including initialisation, as some proof:
DELIMITER ; -- Just in case
DROP TABLE IF EXISTS Topics, Subjects, error_msg;
CREATE TABLE Subjects ( id INT(5) PRIMARY KEY,
subjectname CHAR(20));
CREATE TABLE Topics ( topicname CHAR(20),
subjectID INT(5)
# FOREIGN KEY (subjectID) REFERENCES Subjects(id) - How this check should be done...
);
CREATE TABLE error_msg ( Message VARCHAR(50) );
INSERT INTO Subjects VALUES
('5', 'Arts'),
('55', 'Maths'),
('2342', 'Biology'),
('12345', 'Finance');
DELIMITER $$ -- Where the delimiter would be defined, originally
CREATE TRIGGER InsertOnTopics
BEFORE INSERT ON Topics
FOR EACH ROW
BEGIN
IF (SELECT COUNT(*) FROM Subjects WHERE id=NEW.subjectID)=0 THEN
INSERT error_msg VALUES ('Foreign Key Constraint Violated!');
END IF;
END$$
DELIMITER ;
INSERT INTO Topics VALUES
('Welfare Benefits', '5'),
('Eigenvectors', '55'),
('Mitochondria', '2342'),
('Bank of Dad', '12345'),
('Something else', '555');
SELECT * FROM error_msg;
With "end;", as the original code:
mysql> SOURCE /Users/benpalmer/test.sql
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.02 sec)
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.02 sec)
Query OK, 4 rows affected (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 0
Query OK, 0 rows affected (0.02 sec)
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '('Something else', '555')' at line 6
Empty set (0.00 sec)
mysql>
With "END$$", in my code:
mysql> SOURCE /Users/myUsername/test.sql
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.02 sec)
Query OK, 0 rows affected (0.02 sec)
Query OK, 4 rows affected (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 0
Query OK, 0 rows affected (0.02 sec)
Query OK, 5 rows affected (0.01 sec)
Records: 5 Duplicates: 0 Warnings: 0
+----------------------------------+
| Message |
+----------------------------------+
| Foreign Key Constraint Violated! |
+----------------------------------+
1 row in set (0.00 sec)
mysql>
Other than this, I don't understand why this particular example isn't being done with a proper foreign key constraint. As my first answer... Hope this helps anyone! Was also stuck on this for a while.