How to create functional index on mariadb? - mariadb

I'm trying to create functional index on mariadb 5.5 like below...
MariaDB [testdb]> create table foo(c1 datetime);
Query OK, 0 rows affected (0.43 sec)
MariaDB [testdb]> alter table foo add c2 varchar(10) AS (date_format(c1, '%Y-%m-%d'));
Query OK, 0 rows affected (0.22 sec)
Records: 0 Duplicates: 0 Warnings: 0
MariaDB [testdb]> desc foo;
+-------+-------------+------+-----+---------+---------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+---------+
| c1 | datetime | YES | | NULL | |
| c2 | varchar(10) | YES | | NULL | VIRTUAL |
+-------+-------------+------+-----+---------+---------+
2 rows in set (0.03 sec)
MariaDB [testdb]> create index idx_foo on foo(c1, c2);
ERROR 1904 (HY000): Key/Index cannot be defined on a non-stored computed column
MariaDB [testdb]>
Is there any how to create compositional column based index with VIRUAL column?
Any advice would be appreciated.
Thanks in advance.

See documentation:
Generated (Virtual and Persistent/Stored) Columns
...
MariaDB until 10.2.2
In MariaDB 10.2.2 and before, the following statements apply to
indexes for generated columns:
Defining indexes on VIRTUAL generated columns is not supported.
...
...

Related

global or local indexes on column with duplicate value in Oracle 19C?

I have below table on Oracle19c(I am an oracle newbie). 4 million rows are inserted into the table daily and for now this table have 40 column and 240 million rows.
I usually search the table with user_id and MyTimestamp columns filter query and it takes 10 minutes to return the answer.
Example:
select * from table where user_id=123581 and MyTimestamp between 1657640396 and 1657777396
Note: Duplicate values are stored in the user_id and MyTimestamp columns.
I want partition monthly on MyTimestamp and index on user_id but which global or local indexes is suitable for indexing and how do I do it?
----------------------------------------------------------------------------------------------------
| id | MyTimestamp | Name | user_id ...
----------------------------------------------------------------------------------------------------
| 0 | 1657640396 | John | 123581 ...
| 1 | 1657638832 | Tom | 168525 ...
| 2 | 1657640265 | Tom | 168525 ...
| 3 | 1657640292 | John | 123581 ...
| 4 | 1657640005 | Jack | 896545 ...
--------------------------------------------------------------------------------------------------
If the majority of your queries contain the partition key, then better create LOCAL indexes:
CREATE INDEX index_name ON table_name (MyTimestamp, user_id) LOCAL;
Local indexes are smaller (i.e. the index partition) and thus faster and you don't have to rebuild the index when you drop an outdated partition.

MariaDB select where not equal [duplicate]

This question already has an answer here:
Syntax error due to using a reserved word as a table or column name in MySQL
(1 answer)
Closed 11 months ago.
Surely this will be flagged as a dupe within seconds but I cannot for the life of me figure out what's wrong with this query:
MariaDB [nextcloud]> describe oc_file_locks;
+-------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------------------+------+-----+---------+----------------+
| id | bigint(20) unsigned | NO | PRI | NULL | auto_increment |
| lock | int(11) | NO | | 0 | |
| key | varchar(64) | NO | UNI | NULL | |
| ttl | int(11) | NO | MUL | -1 | |
+-------+---------------------+------+-----+---------+----------------+
4 rows in set (0.003 sec)
MariaDB [nextcloud]> select * from oc_file_locks where lock <> 0;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'lock <> 0' at line 1
MariaDB [nextcloud]> select * from oc_file_locks where lock != 0;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'lock != 0' at line 1
Am I crazy, or should this work? I'm a little rusty on my SQL but I didn't think it was that bad.
key and lock are reserved words. Pick different names, or enclose them in backticks:
select * from oc_file_locks where `lock` <> 0;

MariaDB : Trigger keeps getting syntax error after insert

I have two tables. Table vitamin contains column vitamin_name and price. Table vitamin_variety contains columns price_variety and price_variety_extreme. I want to create an AFTER INSERT Trigger, that will insert the price of vitamin if the value of vitamin_name contains extreme into price_variety_extreme and not contains extreme into price_variety .
Here's what I mean if I insert this into vitamin, the price will be input into vitamin_variety
table = vitamin
+----------------+-------+
| vitamin_name | price |
+----------------+-------+
| extreme pill 1 | 10 |
| pill 1 | 5 |
| extreme pill 2 | 20 |
| pill 2 | 10 |
+----------------+-------+
table = vitamin_variety
+---------------+-----------------------+
| price_variety | price_variety_extreme |
+---------------+-----------------------+
| 5 | 10 |
| 10 | 20 |
+---------------+-----------------------+
my query keeps getting syntax error. it keeps saying
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use
near '' at line 5
what's wrong?
create trigger vitamin_ain after insert on vitamin
for each ROW
if vitamin.vitamin_name like 'extreme%' then
update vitamin_variety
set price_variety_extreme = new.price_variety_extreme;
else if vitamin.vitamin_name not like 'extreme%' then
update vitamin_variety
set price_variety = new.price_variety;
end if;
There are some syntax issues, and other situations, but the conditions inside the trigger could look like the code below:
First, (not right or wrong) the else if could be simplified to an else. If the first condition finds extreme, there is no need to inverse check for not like extreme. (unless some strange requirement expects that handling)
Of course, feel free to keep the else if check as-is, if it makes more sense to you, but I used this code:
if new.vitamin_name like 'extreme%' then
update vitamin_variety
set price_variety_extreme = new.price;
else
update vitamin_variety
set price_variety = new.price;
end if
The 'syntax issues':
In the if condition, change vitamin.vitamin_name to new.vitamin. Columns from trigger insert actions are referenced from new, not the table name.
If keeping your original else if, need to change the same vitamin.vitamin_name reference mentioned in item 1.
References new.price_variety_extreme and new.price_variety do not exist from the vitamin insert (these columns are not in vitamin), but new.price is, and the other vitamin columns.
The 'other situations':
Without any rows already present in the vitamin_variety table, no update will occur, because there are not any rows to update. This situation will make it seem as if the trigger is not working, but there is nothing for the trigger to update.
The desired output to vitamin_variety cannot be achieved with the current info. The update will set ALL columns of one or the other to the last inserted price, because there is no unique row reference. (no WHERE clause to limit what row(s) get updated)
Here's some sample interaction:
As the first other situation mentioned, there are no rows in the vitamin_variety table, so I added one:
MariaDB [test]> insert into vitamin_variety (price_variety, price_variety_extreme) values (0, 0);
Query OK, 1 row affected (0.08 sec)
MariaDB [test]> select * from vitamin_variety;
+----+---------------+-----------------------+
| id | price_variety | price_variety_extreme |
+----+---------------+-----------------------+
| 1 | 0 | 0 |
+----+---------------+-----------------------+
1 row in set (0.00 sec)
Then, with the trigger added to vitamin, inserted a couple of rows:
MariaDB [test]> insert into vitamin( vitamin_name, price ) values ('pilly 5', 7);
Query OK, 1 row affected (0.10 sec)
MariaDB [test]> insert into vitamin( vitamin_name, price ) values ('extreme pill 5', 3);
Query OK, 1 row affected (0.12 sec)
Show those inserts:
MariaDB [test]> select * from vitamin;
+----+----------------+-------+
| id | vitamin_name | price |
+----+----------------+-------+
| 8 | pilly 5 | 7 |
| 9 | extreme pill 5 | 3 |
+----+----------------+-------+
2 rows in set (0.00 sec)
Show the triggered price updates to the vitamin_variety table:
MariaDB [test]> select * from vitamin_variety;
+----+---------------+-----------------------+
| id | price_variety | price_variety_extreme |
+----+---------------+-----------------------+
| 1 | 7 | 3 |
+----+---------------+-----------------------+
1 row in set (0.00 sec)
=====
EDIT:
One possible way to achieve your goal, given this vitamin_variety table structure:
CREATE TABLE `vitamin_variety` (
`pill_name` varchar(25) NOT NULL,
`price_variety` int(11) NOT NULL DEFAULT '0',
`price_variety_extreme` int(11) NOT NULL DEFAULT '0',
UNIQUE KEY `pill_name` (`pill_name`)
);
Then changing the vitamin table trigger conditions to:
if new.vitamin_name like 'extreme%' then
insert into vitamin_variety (pill_name, price_variety_extreme)
values (replace(new.vitamin_name, 'extreme ', ''), new.price)
on duplicate key update price_variety_extreme = new.price;
else
insert into vitamin_variety (pill_name, price_variety)
values (new.vitamin_name, new.price)
on duplicate key update price_variety = new.price;
end if
Then running insert SQL based on your original vitamin table details:
MariaDB [test]> insert into vitamin (vitamin_name, price) values ('extreme pill 1', 10);
Query OK, 1 row affected (0.09 sec)
MariaDB [test]> insert into vitamin (vitamin_name, price) values ('pill 1', 5);
Query OK, 1 row affected (0.16 sec)
MariaDB [test]> insert into vitamin (vitamin_name, price) values ('extreme pill 2', 20);
Query OK, 1 row affected (0.10 sec)
MariaDB [test]> insert into vitamin (vitamin_name, price) values ('pill 2', 10);
Query OK, 1 row affected (0.10 sec)
Gives:
MariaDB [test]> select * from vitamin_variety;
+-----------+---------------+-----------------------+
| pill_name | price_variety | price_variety_extreme |
+-----------+---------------+-----------------------+
| pill 1 | 5 | 10 |
| pill 2 | 10 | 20 |
+-----------+---------------+-----------------------+
2 rows in set (0.00 sec)

What is the default server characterset in mariadb inside the Swisscom Cloud and how can it be changed?

This is a request for clarification concerning the Swisscom Cloud MariaDB Service. This is not about the generic MariaDB default charactersets.
I would like to know what the default character_set_server for the MariaDB Service on the Swisscom Cloud is defined as.
Assuming that it is actually latin1, I would like to know if this default can be changed (to utf-8 or more accurately utf8mb4 as it is for the debian mariadb package).
The main reason for my question is that I am having trouble creating backups that can easily be re-imported and I am getting widely different size output when extracting via mysqldump ... -r backup.sql compared to an export through Sequel Pro.
I don't use the tool Sequel Pro.
The legacy MariaDB/Galera cluster uses latin1 as default character set when you don't set it. This default setting is from upstream MariaDB developers. Most developers and DBAs don't like this decision.
Here is the CREATE TABLE syntax (see COLLATE and CHARACTER SET) :
CREATE TABLE tbl_name (column_list)
[[DEFAULT] CHARACTER SET charset_name]
[COLLATE collation_name]]
Server settings (this statement can every customer execute, no admin rights needed):
MariaDB [(none)]> show global variables like 'character_set%';
+--------------------------+-------------------------------------+
| Variable_name | Value |
+--------------------------+-------------------------------------+
| character_set_client | latin1 |
| character_set_connection | latin1 |
| character_set_database | latin1 |
| character_set_filesystem | binary |
| character_set_results | latin1 |
| character_set_server | latin1 |
| character_set_system | utf8 |
| character_sets_dir | /usr/share/mariadb-galera/charsets/ |
+--------------------------+-------------------------------------+
8 rows in set (0.00 sec)
If you still use legacy MariaDB, please hurry up and migrate your service instance. The legacy cluster will be in one or two days read-only.
We have a completely new MariaDB service in store for you. It comes
with many improvements (e.g. MariaDB version 10) and we recommend to
upgrade as soon as possible.
This step-by-step guide was created Aug 16, 2017.
The new cluster uses better default settings:
MariaDB [(none)]> show global variables like 'character_set%';
+--------------------------+------------------------------------------------------------------------------------------+
| Variable_name | Value |
+--------------------------+------------------------------------------------------------------------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | utf8 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | utf8 |
| character_set_system | utf8 |
| character_sets_dir | /var/vcap/data/packages/mariadb/95a1896c4bcdccb4e1abd81b7d00eb33aedb0da0/share/charsets/ |
+--------------------------+------------------------------------------------------------------------------------------+
8 rows in set (0.01 sec)
If you wish to change your character set and collation before importing the data into new cluster.
ALTER TABLE tbl_name
[[DEFAULT] CHARACTER SET charset_name]
[COLLATE collation_name]
We did this many times. Please keep in mind that you shouldn't do this with > 20000 records.
Please also have a look at our documentation for MariaDB
Please contact Swisscom Application Cloud support when you need to
issue long running DDL changes (for example ALTER TABLE with thousends
of records). Long running DDL causes an outage for all customers on
the cluster.
This is to demonstrate two different ALTERs; one does nothing useful; one does what you want:
-- Try the 'wrong' ALTER:
DROP TABLE IF EXISTS atc;
CREATE TABLE atc ( c VARCHAR(11)) CHARACTER SET latin1 ;
INSERT INTO atc (c) VALUES ('ÃÔäô');
SHOW CREATE TABLE atc\G
SELECT c, HEX(c) FROM atc; -- note the latin1 encoding
ALTER TABLE atc CHARACTER SET utf8;
SHOW CREATE TABLE atc\G -- the column stays latin1, overriding the table
SELECT c, HEX(c) FROM atc; -- still latin1 encoding
mysql>
mysql> -- Try the 'wrong' ALTER:
mysql>
mysql> DROP TABLE IF EXISTS atc;
Query OK, 0 rows affected (0.01 sec)
mysql> CREATE TABLE atc ( c VARCHAR(11)) CHARACTER SET latin1 ;
Query OK, 0 rows affected (0.02 sec)
mysql> INSERT INTO atc (c) VALUES ('ÃÔäô');
Query OK, 1 row affected (0.00 sec)
mysql> SHOW CREATE TABLE atc\G
*************************** 1. row ***************************
Table: atc
Create Table: CREATE TABLE `atc` (
`c` varchar(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
mysql> SELECT c, HEX(c) FROM atc; -- note the latin1 encoding
+----------+----------+
| c | HEX(c) |
+----------+----------+
| ÃÔäô | C3D4E4F4 |
+----------+----------+
1 row in set (0.00 sec)
mysql> ALTER TABLE atc CHARACTER SET utf8;
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> SHOW CREATE TABLE atc\G -- the column stays latin1, overriding the table
*************************** 1. row ***************************
Table: atc
Create Table: CREATE TABLE `atc` (
`c` varchar(11) CHARACTER SET latin1 DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
mysql> SELECT c, HEX(c) FROM atc; -- still latin1 encoding
+----------+----------+
| c | HEX(c) |
+----------+----------+
| ÃÔäô | C3D4E4F4 |
+----------+----------+
1 row in set (0.00 sec)
-- Try the 'right' way:
DROP TABLE IF EXISTS atc;
CREATE TABLE atc ( c VARCHAR(11)) CHARACTER SET latin1 ;
INSERT INTO atc (c) VALUES ('ÃÔäô');
SHOW CREATE TABLE atc\G
SELECT c, HEX(c) FROM atc; -- note the latin1 encoding
ALTER TABLE atc CONVERT TO CHARACTER SET utf8;
SHOW CREATE TABLE atc\G -- column and table are utf8
SELECT c, HEX(c) FROM atc; -- now utf8
mysql>
mysql> -- Try the 'right' way:
mysql>
mysql> DROP TABLE IF EXISTS atc;
Query OK, 0 rows affected (0.01 sec)
mysql> CREATE TABLE atc ( c VARCHAR(11)) CHARACTER SET latin1 ;
Query OK, 0 rows affected (0.01 sec)
mysql> INSERT INTO atc (c) VALUES ('ÃÔäô');
Query OK, 1 row affected (0.00 sec)
mysql> SHOW CREATE TABLE atc\G
*************************** 1. row ***************************
Table: atc
Create Table: CREATE TABLE `atc` (
`c` varchar(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
mysql> SELECT c, HEX(c) FROM atc; -- note the latin1 encoding
+----------+----------+
| c | HEX(c) |
+----------+----------+
| ÃÔäô | C3D4E4F4 |
+----------+----------+
1 row in set (0.00 sec)
mysql> ALTER TABLE atc CONVERT TO CHARACTER SET utf8;
Query OK, 1 row affected (0.03 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> SHOW CREATE TABLE atc\G -- column and table are utf8
*************************** 1. row ***************************
Table: atc
Create Table: CREATE TABLE `atc` (
`c` varchar(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
mysql> SELECT c, HEX(c) FROM atc; -- now utf8
+----------+------------------+
| c | HEX(c) |
+----------+------------------+
| ÃÔäô | C383C394C3A4C3B4 |
+----------+------------------+
1 row in set (0.00 sec)
mysql>

MariaDB ALTER TABLE DROP COLUMN infinite

I use below command to drop a column activetime from my table. While this command never end. I waited for 5 mins while there is only 100 records in MY_TABLENAME
ALTER TABLE MY_TABLENAME DROP COLUMN activetime;
The column activetime is defined as below:
| activetime | bigint(20) | NO | | NULL | |

Resources