Mysql crashed on conditional insert - mysql

I need some condition on insert statement to prevent unauthorized insertions.
I wrote something like this:
INSERT INTO `fund` (amount,description)
SELECT 1000,'Some description'
WHERE 12 IN (SELECT id FROM users WHERE allow_add=1)
Where 12 is the id of current user.
But mysql process stopped unexpectedly!
I use XAMPP with MySQL version: 5.5.5-10.1.13-MariaDB.
Note that I ran this code before this in SQL Server without any problem.
Any Idea?

From users and Where exists work so maybe a bug with in?
MariaDB [sandbox]> delete from t where att = 3;
Query OK, 2 rows affected (0.04 sec)
MariaDB [sandbox]>
MariaDB [sandbox]> select * from t;
+------+------+
| id | att |
+------+------+
| 1 | 1 |
| 1 | 2 |
| 2 | 0 |
+------+------+
3 rows in set (0.00 sec)
MariaDB [sandbox]>
MariaDB [sandbox]> insert into t(id,att)
-> select 4,3
-> from users
-> where id = 1;
Query OK, 1 row affected (0.05 sec)
Records: 1 Duplicates: 0 Warnings: 0
MariaDB [sandbox]>
MariaDB [sandbox]>
MariaDB [sandbox]> select * from t;
+------+------+
| id | att |
+------+------+
| 1 | 1 |
| 1 | 2 |
| 2 | 0 |
| 4 | 3 |
+------+------+
4 rows in set (0.00 sec)
MariaDB [sandbox]>
MariaDB [sandbox]> insert into t(id,att)
-> select 4,3
-> where exists (select 1 from users where id = 1);
Query OK, 1 row affected (0.02 sec)
Records: 1 Duplicates: 0 Warnings: 0
MariaDB [sandbox]>
MariaDB [sandbox]> select * from t;
+------+------+
| id | att |
+------+------+
| 1 | 1 |
| 1 | 2 |
| 2 | 0 |
| 4 | 3 |
| 4 | 3 |
+------+------+
5 rows in set (0.00 sec)

Add semicolon(;) to your query, and what desc is doing in query. It will describe the table structure and its attributes.

It is not a proper way to authorize insertions in database. Instead, you can use programming based solution for this problem.
In PHP, a proper solution could be:-
if ($user->allow_add == 1){ //where $user is the User instance for current user
$sql->query("INSERT INTO `fund` (amount,desc) VALUES(1000,'Some desc')");
}

Try This:
INSERT INTO `fund` (amount,desc)
SELECT 1000 as amt,'Some desc' as des FROM users WHERE allow_add=1 LIMIT 12

With thanks to P.Salmon answer, I found the solution. It seems that MySQL needs FROM statement in conditional SELECT, unlike the SQL Server. So, I add a temporary table name as below:
INSERT INTO `fund` (amount,description)
SELECT 1000,'Some description'
FROM (SELECT 1) t
WHERE 12 IN (SELECT id FROM users WHERE allow_add=1)

Related

MariaDB default function changing PK field with auto increment to null

Take the example of the following query, I am inserting data to the teams table and teamId (type: INT) is the primary key with auto-increment set to true.
'INSERT INTO `teams` (`teamId`,`teamName`,`referralCommission`,`createdAt`,`updatedAt`,`companyId`) VALUES (DEFAULT,?,?,?,?,?);'
This query runs fine on MySQL, but on MariaDB the DEFAULT is being converted to null, which I know is the normal behavior when the default is not set for a column. But in my case, the teamId is auto-incremented so the default should point to the next available id. Instead, teamId is set to 0 (converts from null) for all entries and since the teamId is primary key, I am unable to add new entries to the table.
Any way I can use the default function of MySQL in mariadb? or any other solution for this problem.
P.S I know I can remove the teamId field entirely from the query and it will work, but I need the above query to work as it is.
i cant say what you doing. which MariaDB version you are using ?
sample
MariaDB [bernd]> SELECT VERSION();
+----------------------------------------+
| VERSION() |
+----------------------------------------+
| 10.2.41-MariaDB-1:10.2.41+maria~bionic |
+----------------------------------------+
1 row in set (0.06 sec)
MariaDB [bernd]>
MariaDB [bernd]> TRUNCATE pk_default;
Query OK, 0 rows affected (0.09 sec)
MariaDB [bernd]> SELECT * FROM `pk_default`;
Empty set (0.01 sec)
MariaDB [bernd]> INSERT INTO `pk_default` (`id`, `sid`, `val`)
-> VALUES
-> (DEFAULT, 6, 45);
Query OK, 1 row affected (0.00 sec)
MariaDB [bernd]> SELECT * FROM `pk_default`;
+----+-----+------+
| id | sid | val |
+----+-----+------+
| 1 | 6 | 45 |
+----+-----+------+
1 row in set (0.00 sec)
MariaDB [bernd]> INSERT INTO `pk_default` (`id`, `sid`, `val`)
-> VALUES
-> (DEFAULT, 6, 45);
Query OK, 1 row affected (0.01 sec)
MariaDB [bernd]> SELECT * FROM `pk_default`;
+----+-----+------+
| id | sid | val |
+----+-----+------+
| 1 | 6 | 45 |
| 2 | 6 | 45 |
+----+-----+------+
2 rows in set (0.00 sec)
MariaDB [bernd]> INSERT INTO `pk_default` (`id`, `sid`, `val`)
-> VALUES
-> (DEFAULT, 6, 45);
Query OK, 1 row affected (0.00 sec)
MariaDB [bernd]> SELECT * FROM `pk_default`;
+----+-----+------+
| id | sid | val |
+----+-----+------+
| 1 | 6 | 45 |
| 2 | 6 | 45 |
| 3 | 6 | 45 |
+----+-----+------+
3 rows in set (0.01 sec)
MariaDB [bernd]>

How to update or change auto increment column value in Mysql

I have a table eav_attribute which have a below structure,
I have mistakenly deleted one record from this table with auto increment attribute id column with value 961.
Now I want that column again with same attribute id value.
But when I am inserting that column it is adding with auto increment value i.e. around 1500.
I want to add new coulmn with attribute id 961
I tried to change set AUTO_INCREMENT to 961 before adding column.
ALTER TABLE eav_attribute AUTO_INCREMENT = 961;
But its not working. Please provide any suggestion.
You can override the auto increment column. For example
MariaDB [sandbox]> drop table if exists t;
Query OK, 0 rows affected (0.14 sec)
MariaDB [sandbox]> create table t (id int auto_increment primary key,val varchar(1));
Query OK, 0 rows affected (0.27 sec)
MariaDB [sandbox]> insert into t (val) values
-> ('a'),('b'),('C');
Query OK, 3 rows affected (0.03 sec)
Records: 3 Duplicates: 0 Warnings: 0
MariaDB [sandbox]>
MariaDB [sandbox]> select * from t;
+----+------+
| id | val |
+----+------+
| 1 | a |
| 2 | b |
| 3 | C |
+----+------+
3 rows in set (0.00 sec)
MariaDB [sandbox]>
MariaDB [sandbox]> delete from t where val = 'b';
Query OK, 1 row affected (0.03 sec)
MariaDB [sandbox]>
MariaDB [sandbox]> select * from t;
+----+------+
| id | val |
+----+------+
| 1 | a |
| 3 | C |
+----+------+
2 rows in set (0.00 sec)
MariaDB [sandbox]> insert into t values (2,'b');
Query OK, 1 row affected (0.02 sec)
MariaDB [sandbox]> select * from t;
+----+------+
| id | val |
+----+------+
| 1 | a |
| 2 | b |
| 3 | C |
+----+------+
3 rows in set (0.00 sec)
MariaDB [sandbox]> show create table t;
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| t | CREATE TABLE `t` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`val` varchar(1) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1 |
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
I would strongly advice you test this thoroughly...

How to lock MySQL table(s) from update until two separate select statements execute

I need to lock and perform two select statements on two MySQL/InnoDB tables. Both tables have related row name updateId.
SELECT ..., updateId FROM Table1 WHERE ...
SELECT ..., updateId FROM Table2 WHERE ...
I need to prevent updates, inserts or deletions (any modifications on the tables) until both SELECT statements execute.
Basically I want to prevent any changes to updateId row between the two statements.
I was looking at SELECT ... FOR SHARE and SELECT ... FOR UPDATE but I'm just a bit unclear how it works.
The other process can!! write, but the first process works wit the data at the moment from the transaction.
here is a sample with transaction
MariaDB [trans]> select * from table1;
+----+-------------+
| id | field1 |
+----+-------------+
| 1 | table 1 -1 |
| 2 | table 1 - 2 |
+----+-------------+
2 rows in set (0.001 sec)
MariaDB [trans]> start transaction;
Query OK, 0 rows affected (0.000 sec)
MariaDB [trans]> select * from table1;
+----+-------------+
| id | field1 |
+----+-------------+
| 1 | table 1 -1 |
| 2 | table 1 - 2 |
+----+-------------+
2 rows in set (0.000 sec)
CLIENT 2:
MariaDB [trans]> update table1 set field1 = 'new value' where id = 1;
Query OK, 1 row affected (0.003 sec)
Rows matched: 1 Changed: 1 Warnings: 0
MariaDB [trans]>
MariaDB [trans]> select * from table1;
+----+-------------+
| id | field1 |
+----+-------------+
| 1 | table 1 -1 |
| 2 | table 1 - 2 |
+----+-------------+
2 rows in set (0.001 sec)
MariaDB [trans]> commit;
Query OK, 0 rows affected (0.001 sec)
MariaDB [trans]> select * from table1;
+----+-------------+
| id | field1 |
+----+-------------+
| 1 | new value |
| 2 | table 1 - 2 |
+----+-------------+
2 rows in set (0.001 sec)
MariaDB [trans]>
START TRANSACTION;
SELECT ... FOR UPDATE;
SELECT ... FOR UPDATE;
blah, blah, blah
UPDATE/INSERT/etc (if desired)
COMMIT;
FOR UPDATE means "I might change the rows in this SELECT, so keep your hands off!"

what syntax to use to update a SET column in mysql?

I created a column called oilcompany that has SET data (Hunt, Pioneer, Chevron, BP)
I can enter any one of those into the oilcompany column and change from one to another one but I can not figure out how to change from one oilcompany to multiple oilcompany (eg. Hunt and BP)... any suggestion?
In the MySQL documentation there are not examples for UPDATE statements, but I normally use two ways to update these kind of columns:
Using text values
Using numeric values
Creating the test environment
mysql> CREATE TABLE tmp_table(
-> id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
-> oilcompany SET('Hunt', 'Pioneer', 'Chevron', 'BP')
-> );
Query OK, 0 rows affected (0.54 sec)
mysql> INSERT INTO tmp_table(oilcompany) VALUES ('Hunt'), ('Pioneer');
Query OK, 2 rows affected (0.11 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM tmp_table;
+----+------------+
| id | oilcompany |
+----+------------+
| 1 | Hunt |
| 2 | Pioneer |
+----+------------+
2 rows in set (0.00 sec)
Alternative#1: Using Text Values
As a SET is a collection of ENUM elements, and any ENUM element can be treated as a string, then we can do things like:
mysql> UPDATE tmp_table
-> SET oilcompany = 'Hunt,BP'
-> WHERE id = 1;
Query OK, 1 row affected (0.07 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> SELECT * FROM tmp_table;
+----+------------+
| id | oilcompany |
+----+------------+
| 1 | Hunt,BP |
| 2 | Pioneer |
+----+------------+
2 rows in set (0.00 sec)
Alternative#2: Using Numeric Values
Any SET element is stored internally as a 64bit number containing the combination of the bits that represent each SET element.
In our table: 'Hunt'=1, 'Pioneer'=2, 'Chevron'=4, 'BP'=8.
Also, mysql allows to use these numbers instead of text values. If we need to see the numeric value in the select, we need to use the SET column inside a numeric expression (E.g. adding zero).
Let's see the current values:
mysql> SELECT id, oilcompany+0, oilcompany FROM tmp_table;
+----+--------------+------------+
| id | oilcompany+0 | oilcompany |
+----+--------------+------------+
| 1 | 9 | Hunt,BP |
| 2 | 2 | Pioneer |
+----+--------------+------------+
2 rows in set (0.00 sec)
Here 9 = 'Hunt' (1) + 'BP' (8) and 2 = 'Pioneer' (2).
Now, let's change the Pioneer to 'Hunt' (1) + 'Chevron' (4):
mysql> UPDATE tmp_table
-> SET oilcompany = 5
-> WHERE id = 2;
Query OK, 1 row affected (0.08 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> SELECT id, oilcompany+0, oilcompany FROM tmp_table;
+----+--------------+--------------+
| id | oilcompany+0 | oilcompany |
+----+--------------+--------------+
| 1 | 9 | Hunt,BP |
| 2 | 5 | Hunt,Chevron |
+----+--------------+--------------+
2 rows in set (0.00 sec)

Slow InfiniDB queries, what am I doing wrong?

I'm testing the InfiniDB community edition to see if it suits our needing.
I imported in a single table about 10 millions rows (loading of data was surprisingly fast), and I'm trying to do some query on it, but these are the results (with NON cached queries.. if query caching exists in InfiniDB):
Query 1 (very fast):
select * from mytable limit 150000,1000
1000 rows in set (0.04 sec)
Query 2 (immediate):
select count(*) from mytable;
+----------+
| count(*) |
+----------+
| 9429378 |
+----------+
1 row in set (0.00 sec)
Ok it seems to be amazingly fast.. but:
Query 3:
select count(title) from mytable;
.. still going after several minutes
Query 4:
select id from mytable where id like '%ABCD%';
+------------+
| id |
+------------+
| ABCD |
+------------+
1 row in set (11 min 17.30 sec)
I must be doing something wrong, it's not possible that it's performing this way with so simple queries. Any Idea?
That shouldn't be the case, there does appear to be something odd going on, see quick test below.
What is your server configuration: memory/OS/CPU and platform (dedicated, virtual, cloud).
Could I get the schema declaration and method to load the data?
Which version are you using? Version 4 community has significantly more features than prior versions, i.e. core syntax matches enterprise.
Cheers,
Jim T
mysql> insert into mytable select a, a from (select hex(rand() * 100000) a from lineitem limit 10000000) b;
Query OK, 10000000 rows affected (1 min 54.12 sec)
Records: 10000000 Duplicates: 0 Warnings: 0
mysql> desc mytable;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | varchar(32) | YES | | NULL | |
| title | varchar(32) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.01 sec)
mysql> select * from mytable limit 150000,1000;
+-------+-------+
| id | title |
+-------+-------+
| E81 | E81 |
| 746A | 746A |
. . .
| DFC8 | DFC8 |
| 2C56 | 2C56 |
+-------+-------+
1000 rows in set (0.07 sec)
mysql> select count(*) from mytable;
+----------+
| count(*) |
+----------+
| 10000000 |
+----------+
1 row in set (0.06 sec)
mysql> select count(title) from mytable;
+--------------+
| count(title) |
+--------------+
| 10000000 |
+--------------+
1 row in set (0.09 sec)
mysql> select id from mytable where id like '%ABCD%' limit 1;
+------+
| id |
+------+
| ABCD |
+------+
1 row in set (0.03 sec)