Mariadb check constraint with subquerie on current table - constraints

Is it possible to do check constraint with subquery on maria db table like this:
CREATE TABLE `tbl` (
`id` int NOT NULL,
`start` datetime NOT NULL,
`end` datetime NOT NULL,
CONSTRAINT C1 CHECK (id not in (select id from tbl as tt where tt.start between start and end or tt.end between start and end)),
CONSTRAINT C2 CHECK (end>start)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
I got error: ERROR 1146 (42S02): Table 'test.tbl' doesn't exist

You're trying to access an object that doesn't exist (Table 'tbl'), you are trying to create it:
MariaDB [_]> DROP TABLE IF EXISTS `tbl`;
Query OK, 0 rows affected (0.01 sec)
MariaDB [_]> CREATE TABLE IF NOT EXISTS `tbl` (
-> `id` INT NOT NULL,
-> `start` DATETIME NOT NULL,
-> `end` DATETIME NOT NULL,
-> CONSTRAINT `C1` CHECK (`id` NOT IN
-> (SELECT `id`
-> FROM `tbl` AS `tt`
-> WHERE `tt`.`start` BETWEEN `start` AND `end` OR
-> `tt`.`end` BETWEEN `start` AND `end`)
-> ),
-> CONSTRAINT `C2` CHECK (`end` > `start`)
-> );
ERROR 1146 (42S02): Table '_.tbl' doesn't exist
In case of access to an object that does exist:
MariaDB [_]> DROP TABLE IF EXISTS `tbl_TEMP`, `tbl`;
Query OK, 0 rows affected, 2 warnings (0.00 sec)
MariaDB [_]> CREATE TABLE IF NOT EXISTS `tbl_TEMP` (
-> `id` INT NOT NULL,
-> `start` DATETIME NOT NULL,
-> `end` DATETIME NOT NULL
-> );
Query OK, 0 rows affected (0.00 sec)
MariaDB [_]> CREATE TABLE IF NOT EXISTS `tbl` (
-> `id` INT NOT NULL,
-> `start` DATETIME NOT NULL,
-> `end` DATETIME NOT NULL,
-> CONSTRAINT `C1` CHECK (
-> `id` NOT IN (SELECT `id`
-> FROM `tbl_TEMP` AS `tt`
-> WHERE `tt`.`start` BETWEEN `start` AND `end` OR
-> `tt`.`end` BETWEEN `start` AND `end`)
-> ),
-> CONSTRAINT `C2` CHECK (`end` > `start`)
-> );
ERROR 1901 (HY000): Function or expression 'select ...'
cannot be used in the CHECK clause of `C1`
An option that may be useful:
MariaDB [_]> DROP TABLE IF EXISTS `tbl`;
Query OK, 0 rows affected, 1 warning (0.00 sec)
MariaDB [_]> CREATE TABLE IF NOT EXISTS `tbl` (
-> `id` INT NOT NULL,
-> `start` DATETIME NOT NULL,
-> `end` DATETIME NOT NULL,
-> CONSTRAINT `C2` CHECK (`end` > `start`)
-> );
Query OK, 0 rows affected (0.00 sec)
MariaDB [_]> DELIMITER //
MariaDB [_]> CREATE TRIGGER `trg_bi_idduplicate` BEFORE INSERT ON `tbl`
-> FOR EACH ROW
-> BEGIN
-> IF EXISTS (SELECT NULL
-> FROM `tbl`
-> WHERE `id` = NEW.`id`) THEN
-> SIGNAL SQLSTATE '45000' SET
-> MYSQL_ERRNO = 31001,
-> MESSAGE_TEXT = '`id` DUPLICATE';
-> END IF;
-> END//
Query OK, 0 rows affected (0.00 sec)
MariaDB [_]> DELIMITER ;
MariaDB [_]> INSERT INTO `tbl`
-> SELECT 1, '2000-01-01 00:00:01', '2000-01-01 00:00:01';
ERROR 4025 (23000): CONSTRAINT `C2` failed for `_`.`tbl`
MariaDB [_]> INSERT INTO `tbl`
-> SELECT 1, '2000-01-01 00:00:01', '2000-01-01 00:00:02';
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
MariaDB [_]> SELECT
-> `id`,
-> `start`,
-> `end`
-> FROM
-> `tbl`;
+----+---------------------+---------------------+
| id | start | end |
+----+---------------------+---------------------+
| 1 | 2000-01-01 00:00:01 | 2000-01-01 00:00:02 |
+----+---------------------+---------------------+
1 row in set (0.00 sec)
MariaDB [_]> INSERT INTO `tbl`
-> SELECT 1, '2000-01-01 00:00:01', '2000-01-01 00:00:02';
ERROR 31001 (45000): `id` DUPLICATE
MariaDB [_]> SELECT
-> `id`,
-> `start`,
-> `end`
-> FROM
-> `tbl`;
+----+---------------------+---------------------+
| id | start | end |
+----+---------------------+---------------------+
| 1 | 2000-01-01 00:00:01 | 2000-01-01 00:00:02 |
+----+---------------------+---------------------+
1 row in set (0.00 sec)

Related

Constraints about

What constraints are copied with table when we create table by using create table as select statement..?
I don't know about MySQL, but - as of Oracle - only the NOT NULL constraint. Even if there was a column designed as a primary key (which - implicitly - means that it can't be NULL), newly created table won't have that constraint.
For example:
SQL> create table test_1
2 (id number primary key,
3 name varchar2(20) not null);
Table created.
SQL> select constraint_name, constraint_Type from user_constraints where table_name = 'TEST_1';
CONSTRAINT_NAME C
-------------------- -
SYS_C009194 C --> "C"heck (NOT NULL) constraint
SYS_C009195 P --> "P"rimary key constraint
SQL> create table test_2 as select * from test_1;
Table created.
SQL> select constraint_name, constraint_Type from user_constraints where table_name = 'TEST_2';
CONSTRAINT_NAME C
-------------------- -
SYS_C009196 C --> that's the "C"heck - NOT NULL constraint
SQL> desc test_2
Name Null? Type
----------------------------------------- -------- ----------------------------
ID NUMBER
NAME NOT NULL VARCHAR2(20)
SQL>
MySQL would only preserve NOT NULL as constarint
CREATE TABLE tab1(id int AUTO_INCREMENT PRIMARY KEY)
create table tab2
(id int primary key,
col1 varchar(20) not null,
col2 int UNIQUE,
col3 int, FOREIGN KEY (col3) REFERENCES tab1(id))
CREATE TABLE tab3 AS SELECT * FROM tab2
Records: 0 Duplicates: 0 Warnings: 0
SHOW CREATE TABLE tab3
Table
Create Table
tab3
CREATE TABLE `tab3` (  `id` int NOT NULL,  `col1` varchar(20) NOT NULL,  `col2` int DEFAULT NULL,  `col3` int DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
fiddle

MARIADB sequences - incrementing by 2

I have the following MARIADB code. It's supposed to demonstrate:
Constructing tables using sequences for incrementing the ID.
Using a temporary table+join to INSERT data into a table, while incrementing the ID.
Procedure:
Sequence S1 and table T1 are created. T1_ID is incremented with S1
Sequence S2 and table T2 are created. T2_ID is incremented with S2
Table T1 is filled with data. All is fine.
Temporary table TEMP_T2 is created and filled with data. No ID in this table. Column T1_NAME is a cross reference to SHORT_NAME in table T1.
The T1_ID is introduced into table TEMP_T2 with a join. The result of this SELECT is inserted into T2. Here, the sequence S2 should auto-increment T2_ID.
For some reason, at the end, T2 looks like this:
T2_ID|T1_ID|NAME|
-----+-----+----+
2| 1|y |
4| 2|x |
6| 2|z |
Why was T2_ID double-incremented?
Thanks!
USE DB1;
SET FOREIGN_KEY_CHECKS = 0;
DROP SEQUENCE IF EXISTS `S2`;
DROP SEQUENCE IF EXISTS `S1`;
DROP TABLE IF EXISTS `T2`;
DROP TABLE IF EXISTS `T1`;
-- Create sequence S1 and able T1
CREATE SEQUENCE `S1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB;
SELECT SETVAL(`S1`, 1, 0);
CREATE TABLE `T1` (
`T1_ID` tinyint(4) NOT NULL DEFAULT nextval(`S1`),
`SHORT_NAME` varchar(10) NOT NULL,
PRIMARY KEY (`T1_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
-- Create sequence T2 and table T2
CREATE SEQUENCE `S2` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB;
SELECT SETVAL(`S2`, 1, 0);
CREATE TABLE `T2` (
`T2_ID` int(11) NOT NULL DEFAULT nextval(`S2`),
`T1_ID` int(11) DEFAULT NULL,
`NAME` varchar(100) DEFAULT NULL COLLATE 'utf8mb3_bin',
PRIMARY KEY (`T2_ID`),
UNIQUE KEY `T2_NAME_UN` (`NAME`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
-- Load data into T1
DELETE FROM T1;
INSERT INTO T1(SHORT_NAME) VALUES
('a'),
('b'),
('c');
SELECT * FROM T1;
-- Create temporary file for joining with T1
DROP TABLE IF EXISTS `TEMP_T2`;
CREATE TEMPORARY TABLE `TEMP_T2` (
`T1_NAME` varchar(10) DEFAULT NULL,
`NAME` varchar(100) DEFAULT NULL,
UNIQUE KEY `T2_NAME_UN` (`NAME`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
DELETE FROM TEMP_T2 ;
-- Insert data into the temporary table
INSERT INTO TEMP_T2(T1_NAME,NAME) VALUES
('b','x'),
('a','y'),
('b','z');
SELECT * FROM TEMP_T2;
# Do a join with TEMP_T2 x T1 and insert into T2
INSERT INTO T2(T1_ID,NAME)
SELECT
t1.T1_ID ,
t2.NAME
FROM TEMP_T2 AS t2
INNER JOIN T1 AS t1
ON t2.T1_NAME =t1.SHORT_NAME ;
SELECT * FROM T2;
Thanks for the responses.
I'm using SEQUENCE rather than AUTO_INCREMENT because I was told that it is the more modern way. It also enables retrieving the last ID of any specific table.
It's strange that this should be a bug. It seems like really basic functionality. But so it is...
I've found this as a reported existing bug MDEV-29540 in INSERT ... SELECT as it pertains to sequences in default values of columns.
Because this bug is reported and fix, this problem is/will not occur in the 10.3.37, 10.4.27, 10.5.18, 10.6.11, 10.7.7, 10.8.6, 10.9.4, 10.10.2, 10.11.1 and later versions.

MariaDB limit value of column

I want to limit the value of the column limited_column, where 0 >= limited_column <= 100 SQL side, on MariaDB
I've tried creating a trigger on INSERT ad UPDATE as such:
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`username` varchar(25) NOT NULL,
`user_id` int(100) NOT NULL,
`limited_column` bigint(20) unsigned NOT NULL DEFAULT '0',
[...]
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
DELIMITER $$
CREATE TRIGGER `limited_column_check_on_insert_trigger` BEFORE INSERT ON `users` FOR EACH ROW
BEGIN
DECLARE dummy,baddataflag INT;
SET baddataflag = 0;
IF NEW.limited_column > 100 THEN
SET baddataflag = 1;
END IF;
IF NEW.limited_column < 0 THEN
SET baddataflag = 1;
END IF;
IF baddataflag = 1 THEN
SELECT CONCAT('Cannot INSERT new value because limited_column is > 100, value was ',NEW.limited_column)
INTO dummy FROM information_schema.tables;
END IF;
END; $$
CREATE TRIGGER `limited_column_check_on_update_trigger` BEFORE UPDATE ON `users` FOR EACH ROW
BEGIN
DECLARE dummy,baddataflag INT;
SET baddataflag = 0;
IF NEW.limited_column > 100 THEN
SET baddataflag = 1;
END IF;
IF NEW.limited_column < 0 THEN
SET baddataflag = 1;
END IF;
IF baddataflag = 1 THEN
SELECT CONCAT('Cannot UPDATE new value because limited_column is > 100, value was ',NEW.limited_column)
INTO dummy FROM information_schema.tables;
END IF;
END; $$
DELIMITER ;
This is what I get if I try inserting a new user when limited_column > 100 (limited_column > 100 works):
MariaDB [NameOfADatabase]> INSERT INTO users (username,user_id,limited_column,[...]) VALUES ('testestes',1,1000,[...]);
ERROR 1172 (42000): Result consisted of more than one row
MariaDB [NameOfADatabase]> INSERT INTO users (username,user_id,limited_column,[...]) VALUES ('testestes',2,100,[...]);
Query OK, 1 row affected (0.02 sec)
Any ideas on what I can do to make this more graceful?
This is running on 10.1.38-MariaDB-0ubuntu0.18.04.2 Ubuntu 18.04
Upgrading to 10.3.15 was the best solution for this, as I can use the CHECK option. Thanks to #RickJames for the info about the update.
Here's the Schema I'm using that works:
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`username` varchar(25) NOT NULL,
`user_id` int(100) NOT NULL,
`limited_column` bigint(20) unsigned NOT NULL DEFAULT '0',
[...]
PRIMARY KEY (`user_id`),
CHECK (limited_column<=100)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
Here's the output I get:
MariaDB [NameOfADatabase]> INSERT INTO users (username,user_id,limited_column,[...]) VALUES ('test1',1,100,[...]);
Query OK, 1 row affected (0.016 sec)
MariaDB [NameOfADatabase]> INSERT INTO users (username,user_id,limited_column,[...]) VALUES ('test2',2,101,[...]);
ERROR 4025 (23000): CONSTRAINT `CONSTRAINT_1` failed for `NameOfADatabase`.`users`

Too long alter/create table InnoDB

I want to try InnoDB (change MyISAM engine). Insert/delete/update works fine (with transaction). Select looks good. Alter and create InnoDB tables is terrible.
Compare create/alter InnoDB and MyISAM tables:
MariaDB [temp_db]> CREATE TABLE `table_InnoDB` (
-> `id` int(10) unsigned NOT NULL DEFAULT 0,
-> `name` varchar(120) NOT NULL DEFAULT '',
-> `name_1` varchar(120) NOT NULL DEFAULT '',
-> `name_2` varchar(120) NOT NULL DEFAULT '',
-> `name_ms` varchar(250) NOT NULL DEFAULT '',
-> `name_ws` varchar(250) NOT NULL DEFAULT '',
-> `name_wa` varchar(250) NOT NULL DEFAULT '',
-> `name_t` varchar(250) NOT NULL DEFAULT '',
-> `name_o` varchar(250) NOT NULL DEFAULT '',
-> `street` varchar(250) NOT NULL DEFAULT '',
-> `street_t` varchar(250) NOT NULL DEFAULT '',
-> `lat` decimal(8,4) NOT NULL DEFAULT 0.0000,
-> `lng` decimal(8,4) NOT NULL DEFAULT 0.0000,
-> `latlng` varchar(15) NOT NULL DEFAULT '0',
-> `geohash` char(4) NOT NULL DEFAULT '',
-> `phone` varchar(50) NOT NULL DEFAULT '',
-> `website` varchar(100) NOT NULL DEFAULT '',
-> `facebook_id` varchar(32) NOT NULL DEFAULT '',
-> `city_id` int(10) unsigned NOT NULL DEFAULT 0,
-> `gd_city_id` int(10) unsigned NOT NULL DEFAULT 0
-> ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (3.235 sec)
MariaDB [temp_db]> CREATE TABLE `table_MyISAM` (
-> `id` int(10) unsigned NOT NULL DEFAULT 0,
-> `name` varchar(120) NOT NULL DEFAULT '',
-> `name_1` varchar(120) NOT NULL DEFAULT '',
-> `name_2` varchar(120) NOT NULL DEFAULT '',
-> `name_ms` varchar(250) NOT NULL DEFAULT '',
-> `name_ws` varchar(250) NOT NULL DEFAULT '',
-> `name_wa` varchar(250) NOT NULL DEFAULT '',
-> `name_t` varchar(250) NOT NULL DEFAULT '',
-> `name_o` varchar(250) NOT NULL DEFAULT '',
-> `street` varchar(250) NOT NULL DEFAULT '',
-> `street_t` varchar(250) NOT NULL DEFAULT '',
-> `lat` decimal(8,4) NOT NULL DEFAULT 0.0000,
-> `lng` decimal(8,4) NOT NULL DEFAULT 0.0000,
-> `latlng` varchar(15) NOT NULL DEFAULT '0',
-> `geohash` char(4) NOT NULL DEFAULT '',
-> `phone` varchar(50) NOT NULL DEFAULT '',
-> `website` varchar(100) NOT NULL DEFAULT '',
-> `facebook_id` varchar(32) NOT NULL DEFAULT '',
-> `city_id` int(10) unsigned NOT NULL DEFAULT 0,
-> `gd_city_id` int(10) unsigned NOT NULL DEFAULT 0
-> ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.564 sec)
# alter empty tables
MariaDB [temp_db]> alter table `table_InnoDB`
-> add primary key (id),
-> add index (street(50), name(50)),
-> add index (street(50), city_id),
-> add index (street(50), gd_city_id),
-> add index (name(50), website),
-> add index (website, city_id),
-> add index (website, gd_city_id),
-> add index (phone, website),
-> add index (phone, name(50)),
-> add index (latlng, name(50)),
-> add index (city_id, name(50)),
-> add index (gd_city_id, name(50)),
-> add index (name_t(50), street(50)),
-> add index (street_t(50), name_t(50)),
-> add index (name_t(50), website),
-> add index (name_t(50), phone);
Query OK, 0 rows affected (11.812 sec)
Records: 0 Duplicates: 0 Warnings: 0
MariaDB [temp_db]> alter table `table_MyISAM`
-> add primary key (id),
-> add index (street(50), name(50)),
-> add index (street(50), city_id),
-> add index (street(50), gd_city_id),
-> add index (name(50), website),
-> add index (website, city_id),
-> add index (website, gd_city_id),
-> add index (phone, website),
-> add index (phone, name(50)),
-> add index (latlng, name(50)),
-> add index (city_id, name(50)),
-> add index (gd_city_id, name(50)),
-> add index (name_t(50), street(50)),
-> add index (street_t(50), name_t(50)),
-> add index (name_t(50), website),
-> add index (name_t(50), phone);
Query OK, 0 rows affected (0.681 sec)
Records: 0 Duplicates: 0 Warnings: 0
# still empty tables
MariaDB [temp_db]> ALTER TABLE `table_InnoDB`
-> DROP PRIMARY KEY,
-> DROP INDEX `name_t_3`,
-> DROP INDEX `name_t_2`,
-> DROP INDEX `street_t`,
-> DROP INDEX `name_t`,
-> DROP INDEX `gd_city_id`,
-> DROP INDEX `city_id`,
-> DROP INDEX `latlng`,
-> DROP INDEX `phone_2`,
-> DROP INDEX `phone`,
-> DROP INDEX `website_2`,
-> DROP INDEX `website`,
-> DROP INDEX `name`,
-> DROP INDEX `street_3`,
-> DROP INDEX `street_2`,
-> DROP INDEX `street`;
Query OK, 0 rows affected (6.149 sec)
Records: 0 Duplicates: 0 Warnings: 0
MariaDB [temp_db]> ALTER TABLE `table_MyISAM`
-> DROP PRIMARY KEY,
-> DROP INDEX `name_t_3`,
-> DROP INDEX `name_t_2`,
-> DROP INDEX `street_t`,
-> DROP INDEX `name_t`,
-> DROP INDEX `gd_city_id`,
-> DROP INDEX `city_id`,
-> DROP INDEX `latlng`,
-> DROP INDEX `phone_2`,
-> DROP INDEX `phone`,
-> DROP INDEX `website_2`,
-> DROP INDEX `website`,
-> DROP INDEX `name`,
-> DROP INDEX `street_3`,
-> DROP INDEX `street_2`,
-> DROP INDEX `street`;
Query OK, 0 rows affected (0.730 sec)
Records: 0 Duplicates: 0 Warnings: 0
# insert data
MariaDB [temp_db]> INSERT table_InnoDB (`id`, `name`, `name_1`, `name_2`, `name_ms`, `name_ws`, `name_wa`, `name_t`, `name_o`, `street`, `street_t`, `lat`, `lng`, `latlng`, `geohash`, `phone`, `website`, `facebook_id`, `city_id`, `gd_city_id`) SELECT `id`, `name`, `name_1`, `name_2`, `name_ms`, `name_ws`, `name_wa`, `name_t`, `name_o`, `street`, `street_t`, `lat`, `lng`, `latlng`, `geohash`, `phone`, `website`, `facebook_id`, `city_id`, `gd_city_id` FROM test_data;
Query OK, 127451 rows affected (53.041 sec)
Records: 127451 Duplicates: 0 Warnings: 0
MariaDB [temp_db]> INSERT table_MyISAM (`id`, `name`, `name_1`, `name_2`, `name_ms`, `name_ws`, `name_wa`, `name_t`, `name_o`, `street`, `street_t`, `lat`, `lng`, `latlng`, `geohash`, `phone`, `website`, `facebook_id`, `city_id`, `gd_city_id`) SELECT `id`, `name`, `name_1`, `name_2`, `name_ms`, `name_ws`, `name_wa`, `name_t`, `name_o`, `street`, `street_t`, `lat`, `lng`, `latlng`, `geohash`, `phone`, `website`, `facebook_id`, `city_id`, `gd_city_id` FROM test_data;
Query OK, 127451 rows affected (1.125 sec)
Records: 127451 Duplicates: 0 Warnings: 0
# alter tables with 127451 rows
MariaDB [temp_db]> alter table `table_InnoDB`
-> add primary key (id),
-> add index (street(50), name(50)),
-> add index (street(50), city_id),
-> add index (street(50), gd_city_id),
-> add index (name(50), website),
-> add index (website, city_id),
-> add index (website, gd_city_id),
-> add index (phone, website),
-> add index (phone, name(50)),
-> add index (latlng, name(50)),
-> add index (city_id, name(50)),
-> add index (gd_city_id, name(50)),
-> add index (name_t(50), street(50)),
-> add index (street_t(50), name_t(50)),
-> add index (name_t(50), website),
-> add index (name_t(50), phone);
Query OK, 0 rows affected (32 min 33.282 sec)
Records: 0 Duplicates: 0 Warnings: 0
MariaDB [temp_db]> alter table `table_MyISAM`
-> add primary key (id),
-> add index (street(50), name(50)),
-> add index (street(50), city_id),
-> add index (street(50), gd_city_id),
-> add index (name(50), website),
-> add index (website, city_id),
-> add index (website, gd_city_id),
-> add index (phone, website),
-> add index (phone, name(50)),
-> add index (latlng, name(50)),
-> add index (city_id, name(50)),
-> add index (gd_city_id, name(50)),
-> add index (name_t(50), street(50)),
-> add index (street_t(50), name_t(50)),
-> add index (name_t(50), website),
-> add index (name_t(50), phone);
Query OK, 127451 rows affected (5.976 sec)
Records: 127451 Duplicates: 0 Warnings: 0
10.3.13-MariaDB config:
datadir=/var/lib/mysql
tmpdir = /mnt/ssd/tmp/
socket=/var/lib/mysql/mysql.sock
symbolic-links=1
key_buffer_size = 1G
max_connections = 300
max_user_connections = 280
table_open_cache = 42192
open_files_limit = 165832
max_allowed_packet = 16M
log_warnings = 0
extra_port = 3307
extra_max_connections = 4
sql_mode = NO_ENGINE_SUBSTITUTION
performance_schema = ON
###############innodb###############
innodb_file_per_table = ON
innodb_sort_buffer_size = 8M
innodb_buffer_pool_size = 15G
innodb_buffer_pool_instances = 15
innodb_write_io_threads = 8
innodb_read_io_threads = 8
innodb_log_file_size = 2G
innodb_flush_log_at_trx_commit = 2
####################################
sort_buffer_size = 12M
read_buffer_size = 2M
join_buffer_size = 4M
thread_cache_size = 256
thread_stack=512K
thread_handling = one-thread-per-connection
thread_pool_max_threads = 500
read_rnd_buffer_size = 16M
net_buffer_length = 1048576
net_read_timeout = 600
net_write_timeout = 600
myisam_sort_buffer_size = 128M
aria_sort_buffer_size = 2G
aria_pagecache_buffer_size = 2G
query_cache_type = OFF
max_heap_table_size = 512M
tmp_table_size = 512M
character-set-server=utf8
collation-server=utf8_general_ci
init-connect="SET NAMES utf8"
default_storage_engine="MyISAM"
slow_query_log_file = /var/log/mariadb/mariadb-slow.log
long-query-time = 5
slow_query_log = 0
skip-name-resolve
low_priority_updates = 1
During alter table SSD busy 100%, but have only several hundred iops and several MB/s read/write.
Other test: Server vs myworkstation
Server (SSD busy 100% after alter tables engine=InnoDB: several light cron scripts + replication):
MariaDB [temp_db]> ALTER TABLE `temp_db`.`table_MyISAM` ADD COLUMN `tmp` VARCHAR(45) NOT NULL DEFAULT '' AFTER `gd_city_id`;
Query OK, 127451 rows affected (6.149 sec)
Records: 127451 Duplicates: 0 Warnings: 0
MariaDB [temp_db]> ALTER TABLE `temp_db`.`table_InnoDB` ADD COLUMN `tmp` VARCHAR(45) NOT NULL DEFAULT '' AFTER `gd_city_id`;
Query OK, 0 rows affected (11.830 sec)
Records: 0 Duplicates: 0 Warnings: 0
MariaDB [temp_db]> ALTER TABLE `table_MyISAM` DROP COLUMN `tmp`;
Query OK, 127451 rows affected (5.182 sec)
Records: 127451 Duplicates: 0 Warnings: 0
MariaDB [temp_db]> ALTER TABLE `table_InnoDB` DROP COLUMN `tmp`;
Query OK, 0 rows affected (18 min 36.757 sec)
Records: 0 Duplicates: 0 Warnings: 0
my PC:
MariaDB [test]> ALTER TABLE `table_MyISAM` ADD COLUMN `tmp` VARCHAR(45) NOT NULL DEFAULT '' AFTER `gd_city_id`;
Query OK, 127451 rows affected (2.897 sec)
Records: 127451 Duplicates: 0 Warnings: 0
MariaDB [test]> ALTER TABLE `table_InnoDB` ADD COLUMN `tmp` VARCHAR(45) NOT NULL DEFAULT '' AFTER `gd_city_id`;
Query OK, 0 rows affected (0.009 sec)
Records: 0 Duplicates: 0 Warnings: 0
MariaDB [test]> ALTER TABLE `table_MyISAM` DROP COLUMN `tmp`;
Query OK, 127451 rows affected (2.822 sec)
Records: 127451 Duplicates: 0 Warnings: 0
MariaDB [test]> ALTER TABLE `table_InnoDB` DROP COLUMN `tmp`;
Query OK, 0 rows affected (2.879 sec)
Records: 0 Duplicates: 0 Warnings: 0
Server: 49GB RAM, 32 CPU.

Copy nested table's values in another tuple of same table

I have the following table in oracle 11g named parlamentari:
cf varchar(16)
nome varchar(20)
cognome varchar(20)
telefoni telefoni_NT
where telefoni_NT is a nested table of varchar2.
Now, I must to copyed the elements of the nested table of a tuple (sorgente) in another tuple (ricevente).
I try to write an example
Start situation
parlamentari
-------------------------------------
cf | nome | cognome | telefoni
-------------------------------------
1 | a | aa | VARCHAR(222,444)
2 | b | bb | VARCHAR(111)
Situation after procedure called
parlamentari
-------------------------------------
cf | nome | cognome | telefoni
-------------------------------------
1 | a | aa | VARCHAR(222,444)
2 | b | bb | VARCHAR(111, 222, 444)
I tried to written this procedure without success
create or replace procedure copia_telefoni2
(sorgente in parlamento2018.parlamentari.cf%type,
ricevente in parlamento2018.parlamentari.cf%type) as
cursor cur_out_tel is
select column_value as original_list
from parlamentari, table(telefoni)
where cf = sorgente
;
cursor in_parlamentare is
select column_value as copied_list
from parlamentari, table(telefoni)
where cf = destinazione;
begin
if (sorgente <> destinazione) then
for i in cur_out_tel loop
dbms_output.put_line(i.original_list);
insert into table(select telefoni from parlamentari where cf=destinazione) values (telefoni_nt(i.original_list));
end loop;
else
dbms_output.put_line('Errore! Sorgente e destinazione uguali');
end if;
end copia_telefoni2;
Copy nested table's values in another tuple of same table
As far i could understand your requirement, you don't need to insert in the table since the record already exists in your table. All you need is to update the existing record. Since your table column is a nested table,MULTISET UNION is something which would work in your situation. See below demo:
Tables:
CREATE OR REPLACE TYPE telefoni_nt IS TABLE OF VARCHAR2(100);
CREATE TABLE parlamentari (
cf VARCHAR(16),
nome VARCHAR(20),
cognome VARCHAR(20),
telefoni telefoni_nt
)
NESTED TABLE telefoni STORE AS nested_telefoni;
insert into parlamentari values('1','a','aa',telefoni_nt('VARCHAR(222,444)'));
insert into parlamentari values('2','b','bb',telefoni_nt('VARCHAR(111)'));
Output:
SQL> Select CF ,TELEFONI from parlamentari;
CF TELEFONI
-- ------
1 TELEFONI_NT('VARCHAR(222,444)')
2 TELEFONI_NT('VARCHAR(111)')
Procedure:
CREATE OR REPLACE PROCEDURE copia_telefoni2 (
sorgente IN parlamentari.cf%TYPE,
destinazione IN parlamentari.cf%TYPE
) AS
BEGIN
IF ( sorgente <> destinazione )
THEN
--Using MULTISET Operator to merge the destination column element with the source column elements.
UPDATE parlamentari
SET
telefoni = telefoni MULTISET UNION (SELECT telefoni
FROM parlamentari
WHERE cf = sorgente )
WHERE
cf = destinazione;
ELSE
dbms_output.put_line('Errore! Sorgente e destinazione uguali');
END IF;
COMMIT;
END copia_telefoni2;
/
Execution:
SQL> EXEC copia_telefoni2('1','2');
PL/SQL procedure successfully completed.
Result:
SQL> Select CF ,TELEFONI from parlamentari;
CF TELEFONI
-- ------
1 TELEFONI_NT('VARCHAR(222,444)')
2 TELEFONI_NT('VARCHAR(111)','VARCHAR(222,444)')
So you can see in the result that the two rows now have been merged.

Resources