MariaDB 10.4.6 drop field level CHECK constraint problem - mariadb

I have a table like this:
CREATE TABLE test (
height int(10) CHECK(height>5)
);
When I try to remove check constraint by:
ALTER TABLE test DROP CONSTRAINT height;
I got this error message:
ERROR 1091 (42000): Can't DROP CONSTRAINT `height`; check that it exists
Here is the SHOW CREATE TABLE test; command output:
+-------+-------------------------------------------------------------------------------------------------------------------+
| Table | Create Table
|
+-------+-------------------------------------------------------------------------------------------------------------------+
| test | CREATE TABLE `test` (
`height` int(10) DEFAULT NULL CHECK (`height` > 5)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+-------+-------------------------------------------------------------------------------------------------------------------+
And here is the SELECT * from information_schema.table_constraints where TABLE_NAME = 'test'; output:
+--------------------+-------------------+-----------------+------------------+------------+-----------------+
| CONSTRAINT_CATALOG | CONSTRAINT_SCHEMA | CONSTRAINT_NAME | TABLE_SCHEMA | TABLE_NAME | CONSTRAINT_TYPE |
+--------------------+-------------------+-----------------+------------------+------------+-----------------+
| def | test_db | height | test_db | test | CHECK |
+--------------------+-------------------+-----------------+------------------+------------+-----------------+

CREATE TABLE :: Constraint
Expressions
...
MariaDB 10.2.1 introduced two ways to define a constraint:
CHECK(expression) given as part of a column definition.
CONSTRAINT [constraint_name] CHECK (expression)
...
If you define the constraint using the first form (column constraint), you can remove it using MODIFY COLUMN:
ALTER TABLE `test`
MODIFY COLUMN `height` INT(10);
If you use the second form (table constraint), you can remove it using DROP CONSTRAINT:
ALTER TABLE `test`
DROP CONSTRAINT `height`;
See dbfiddle.

Related

MariaDB UPDATE queries extremely slow

I have a user table, for which UPDATE queries are extremely slow to complete. SELECT queries seem fine.
The DB is MariaDB 10.1.48.
CREATE TABLE `user` (
id int(10) UNSIGNED NOT NULL,
active tinyint(1) UNSIGNED NOT NULL DEFAULT '0',
email varchar(100) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
mobile varchar(50) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
isMobile_verified enum('0','1') NOT NULL DEFAULT '0',
device_type enum('0','1','none') NOT NULL DEFAULT 'none' COMMENT '1-Ios,0-Android',
device_token text,
password varchar(255) DEFAULT NULL,
updated datetime NOT NULL,
updated_by int(10) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
ALTER TABLE user
ADD PRIMARY KEY (id),
ADD UNIQUE KEY email (email),
ADD UNIQUE KEY mobile (mobile),
ADD KEY active (active);
ALTER TABLE user
MODIFY id int(10) UNSIGNED NOT NULL AUTO_INCREMENT;
Even via PHPMyAdmin or console, a very basic UPDATE query on an indexed column will take 4 to 5 seconds to run. As this is a core table for my application the cumulative effect causes some transactions to run for up to 40 seconds.
There are only c.190K records in the table. Other tables in the DB, including those of similar or larger size, do not seem to be affected.
Is there some issue with the DB version I should upgrade away from, or perhaps a cache problem? Proplem surfaced in the past few months and seems to be getting progressively worse with time. Any help greatly appreciated.
EDIT: Sample UPDATE query, with EXPLAIN output:
EXPLAIN UPDATE user SET isMobile_verified = 0 WHERE id = 1;
+---------+--------+--------+----------+----------+----------+-------+-------+-------------+
| select | table | type | keys | key | key_len | ref | rows | Extra |
+---------+--------+--------+----------+----------+----------+-------+-------+-------------+
| SIMPLE | user | range | PRIMARY | PRIMARY | 4 | NULL | 1 | Using where |
+---------+--------+--------+----------+----------+----------+-------+-------+-------------+
Foreign key constraints, specifically from other DBs, targeting the ID column had built up over time. Refactoring to remove those constraints (and allow for their removal!) resolves issue.

Loop import XML files

I'm using MariaDB to import some files in XML.
Here is a snippet of the code I'm using:
CREATE TABLE invoices (
InvoiceNumber VARCHAR(20),
InvoiceStatus CHAR (1),
InvoiceDate CHAR (10),
Period CHAR (2)
)
;
DROP TABLE if EXISTS temptbl;
create table temp02 (
InvoiceNumber VARCHAR(20) xpath='InvoiceNo',
InvoiceStatus CHAR(1) xpath='DocumentStatus/InvoiceStatus',
InvoiceDate CHAR (10) xpath='InvoiceDate',
Period CHAR (2) xpath='Period'
)
engine=CONNECT table_type=XML file_name='..\\importmaridb\\month01.xml'
tabname='AuditFile' option_list='rownode=SourceDocuments/SalesInvoices/Invoice';
INSERT INTO invoices
SELECT * FROM temptbl;
I then repeat 12x the code of importing to table "temptbl" changing only the file name to reflect the other months.
I would like to have a loop to iterate the files each time.
I believe part of the solution would be to create a table with the file names and an auto increment column, where I would loop through the numbers.
I've attempted to define a variable and substituting in the code, like file_name=#path. But MariaDB gives me an error a syntax error.
| VARIABLE_NAME | VARIABLE_VALUE | VARIABLE_TYPE | CHARACTER_SET_NAME |
+---------------+----------------+---------------+--------------------+
| path | ..\importmaridb| VARCHAR | utf8mb4 |
| | \month01.xml | | |
Can someone give me some pointers, and even if this is possible?

Weird behavior in mariadb table with unique key defined (ie, not so unique)

I'm trying to export/import a BD from one system to another but the import fails with the following error:
ERROR 1062 (23000) at line 8232: Duplicate entry '0-3-30168717-com_liferay_product_navigation_product_menu_web_...' for key 'IX_C7057FF7'
That table is defined as such:
CREATE TABLE `PortletPreferences` (
`portletPreferencesId` bigint(20) NOT NULL,
`ownerId` bigint(20) DEFAULT NULL,
`ownerType` int(11) DEFAULT NULL,
`plid` bigint(20) DEFAULT NULL,
`portletId` varchar(200) DEFAULT NULL,
`preferences` longtext DEFAULT NULL,
`mvccVersion` bigint(20) NOT NULL DEFAULT 0,
`companyId` bigint(20) DEFAULT NULL,
PRIMARY KEY (`portletPreferencesId`),
UNIQUE KEY `IX_C7057FF7` (`ownerId`,`ownerType`,`plid`,`portletId`),
In the mysql dump file, I see these two entries:
(31453178,0,3,30168717,'com_liferay_product_navigation_product_menu_web_portlet_ProductMenuPortlet','<portlet-preferences />',0,10132)
(31524539,0,3,30168717,'com_liferay_product_navigation_product_menu_web_portlet_ProductMenuPortlet','<portlet-preferences />',0,10132)
So, yep, there are two entries with the same unique key. How is that possible?!?
Knowing this, I ran the following select statement against the source DB:
select portletPreferencesId, ownerId, ownerType, plid, portletId from PortletPreferences where ownerId = 0 AND ownerType = 3 AND plid = 30168717 AND portletId like 'com_liferay_product_navigation_product_menu_web%';
And it outputs just ONE LINE!
+----------------------+---------+-----------+----------+----------------------------------------------------------------------------+
| portletPreferencesId | ownerId | ownerType | plid | portletId |
+----------------------+---------+-----------+----------+----------------------------------------------------------------------------+
| 31524539 | 0 | 3 | 30168717 | com_liferay_product_navigation_product_menu_web_portlet_ProductMenuPortlet |
+----------------------+---------+-----------+----------+----------------------------------------------------------------------------+
By the portletPreferencesId field, it outputs the second entry in the dump file. So I did one more select for the other row as such:
select portletPreferencesId, ownerId, ownerType, plid, portletId from PortletPreferences where portletPreferencesId = 31453178;
And I get:
+----------------------+---------+-----------+----------+----------------------------------------------------------------------------+
| portletPreferencesId | ownerId | ownerType | plid | portletId |
+----------------------+---------+-----------+----------+----------------------------------------------------------------------------+
| 31453178 | 0 | 3 | 30168717 | com_liferay_product_navigation_product_menu_web_portlet_ProductMenuPortlet |
+----------------------+---------+-----------+----------+----------------------------------------------------------------------------+
My question is, what's going on?!? Why is that entry not output by the first select statement and why is it there in the first place if those fields were supposed to be unique???
I have a bad feeling about the state of the source database :-( Oh, and that's just one. I have multiple duplicate keys like that in that table :-(
Thanks
There are occasional bugs like MDEV-15250 that can cause duplicate entries to occur.
Sometimes you may not see these as parts of the optimizer expect only a single row because of the unique constraint so won't search beyond it. Maybe a query across a range including the entries would be more likely to show it (which is what mysqldump would have done).
If you don't think its related to ALTER TABLE occurring at the same time as insertions (like MDEV-15250), and have a good hunch as the set of operations on the table that may have escaped the unique key enforcement, can you please create a bug report.

Make Procedure with SCOPE_IDENTITY()

I got this three tables
CREATE TABLE
(
FirstTableId Int primary key identity,
Something nvarchar(20)
)
CREATE TABLE SecondTable
(
SecondTableId Int primary key identity,
Something nvarchar(20)
)
CREATE TABLE Relation
(
RelationId int primary key identity,
RelationSomething nvarchar(20),
FirstTableId Int,
SecondTableId Int,
FOREIGN KEY (FirstTableId) REFERENCES FirstTable(FirstTableId),
FOREIGN KEY (SecondTableId) REFERENCES SecondTable(SecondTableId),
)
I create this procedure to insert data into FirstTable and Relation:
CREATE PROC InsertInto (#FirstTableId int)
AS
INSERT INTO FirstTable VALUES ('example')
SELECT #FirstTableId = SCOPE_IDENTITY()
INSERT INTO Relation (RelationSomething, FirstTableId, SecondTableId) VALUES ('example', #FirstTableId, 2)
I pass values from dropdownlists for example data, and do not pass anything for #FirstTable, because I expect that it get SCOPE_IDENTITY(), but I got error like this: "Must declare the scalar variable "#FirstTableId"? How can I solve this and make it's work?
You need to declare the variable in the body and not the Stored Procedure definition. When you declare it in the definition, that means you will pass the value when you call the Stored Procedure.
CREATE PROC InsertInto ()
AS
DECLARE #FirstTableId int;
INSERT INTO FirstTable VALUES ('example')
SET #FirstTableId = SCOPE_IDENTITY()
INSERT INTO Relation (RelationSomething, FirstTableId, SecondTableId) VALUES ('example', #FirstTableId, 2)
Do you have a typo in your actual code? Because in your question you say the procedure parameter is #FirstTable and then later say the error is about #FirstTableId, and in the example procedure the name of the parameter is #FirstTableId.
If you do not need to input or output anything from the parameter, declare and use the variable in the procedure.
If you are trying to use an output parameter, then you would declare the parameter as output:
create proc InsertInto (#FirstTableId int output) as
begin;
set nocount, xact_abort on;
insert into FirstTable
values ('example');
select #FirstTableId = scope_identity();
insert into Relation (FirstTableId, SecondTableId) values
(#FirstTableId, 2);
end;
go
and use it like so:
declare #id int;
exec insertinto #id output;
select #id as IdOutput;
returns
+----------+
| IdOutput |
+----------+
| 1 |
+----------+
and the row from the relation table:
select * from relation;
returns
+--------------+---------------+
| firsttableid | secondtableid |
+--------------+---------------+
| 1 | 2 |
+--------------+---------------+
rextester demo: http://rextester.com/VPS78362

correct incrementing of primary key in sqlite

I use sqlite3 and have a simple table
CREATE TABLE `data` (
`item_id` INTEGER,
`item` TEXT NOT NULL UNIQUE,
PRIMARY KEY(item_id)
);
Inserting some values:
INSERT OR IGNORE INTO `data` (`item`) VALUES ('A'), ('A'), ('B');
This will result in:
`item_id` | `item`
----------+-------
1 | A
3 | B
Is it possible to get the incrementing of the primary key in a correct way like:
`item_id` | `item`
----------+-------
1 | A
2 | B
Try adding the AUTOINCREMENT keyword to the 'item_id' column, and then specifying by how much the value increments:
CREATE TABLE `data` (
`item_id` INTEGER AUTOINCREMENT (1, 1),
`item` TEXT NOT NULL UNIQUE,
PRIMARY KEY(item_id)
);
I'm not entirely sure if it will work, but I am working with MS-SQL at the moment, and the syntax for creating a table seems fairly similar.
Hope this helps.

Resources