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 | |
Related
I have a table with a large amount of data; moving forward, I would like to enforce uniqueness for a given column in this table. However, the table contains a large amount of rows where that column is non-unique. I am not able to delete or alter these rows.
Is it possible to enforce uniqueness over a given date range, or since a specific date, or based on the value of another column (or something else like that) in MariaDB?
You can create a UNIQUE index on multiple columns, where one column is nullable. MariaDB will see each column with NULL values as a different value regarding the UNIQUE index, even if the other column values of the UNIQUE index are the same. Check the MariaDB documentation Getting Started with Indexes - Unique Index:
The fact that a UNIQUE constraint can be NULL is often overlooked. In SQL any NULL is never equal to anything, not even to another NULL. Consequently, a UNIQUE constraint will not prevent one from storing duplicate rows if they contain null values:
CREATE TABLE t1 (a INT NOT NULL, b INT, UNIQUE (a,b));
INSERT INTO t1 values (3,NULL), (3, NULL);
SELECT * FROM t1;
+---+------+
| a | b |
+---+------+
| 1 | 1 |
| 2 | 1 |
| 2 | 2 |
| 3 | NULL |
| 3 | NULL |
+---+------+
You can create such a UNIQUE index on the date column you already have and a new column which indicates if the date value should be unique or not:
CREATE TABLE Foobar(
id INT AUTO_INCREMENT PRIMARY KEY NOT NULL,
createdAt DATE NOT NULL,
dateUniqueMarker BIT NULL DEFAULT 0,
UNIQUE KEY uq_createdAt(createdAt, dateUniqueMarker)
);
INSERT INTO Foobar(createdAt) VALUES ('2021-11-04'),('2021-11-05'),('2021-11-06');
SELECT * FROM Foobar;
+----+------------+------------------------------------+
| id | createdAt | dateUniqueMarker |
+----+------------+------------------------------------+
| 1 | 2021-11-04 | 0x00 |
| 2 | 2021-11-05 | 0x00 |
| 3 | 2021-11-06 | 0x00 |
+----+------------+------------------------------------+
INSERT INTO Foobar(createdAt) VALUES ('2021-11-05');
ERROR 1062 (23000): Duplicate entry '2021-11-05-\x00' for key 'Foobar.uq_createdAt'
UPDATE Foobar SET dateUniqueMarker = NULL WHERE createdAt = '2021-11-05';
INSERT INTO Foobar(createdAt, dateUniqueMarker) VALUES ('2021-11-05', NULL);
SELECT * FROM Foobar;
+----+------------+------------------------------------+
| id | createdAt | dateUniqueMarker |
+----+------------+------------------------------------+
| 1 | 2021-11-04 | 0x00 |
| 2 | 2021-11-05 | NULL |
| 5 | 2021-11-05 | NULL |
| 3 | 2021-11-06 | 0x00 |
+----+------------+------------------------------------+
Without any data example and scenario illustration, it's hard to know. If you can update your question with those information, please do.
"Is it possible to enforce uniqueness over a given date range, or since a specific date, or based on the value of another column (or something else like that) in MariaDB?"
If by "enforce" you mean to create a new column then populate it with unique identifier, then yes it is possible. If what you really mean is to generate a unique value based on other column, that's also possible. Question is, how unique do you want it to be?
Is it like this unique?
column1
column2
column3
unique_val
2021-02-02
ABC
DEF
1
2021-02-02
CBD
FEA
1
2021-02-03
BED
GER
2
2021-02-04
ART
TOY
3
2021-02-04
ZSE
KSL
3
Whereby if it's the same date (on column1), it should have the same unique value regardless of column2 & column3 data.
Or like this?
column1
column2
column3
unique_val
2021-02-02
ABC
DEF
1
2021-02-02
CBD
FEA
2
2021-02-03
BED
GER
3
2021-02-04
ART
TOY
4
2021-02-04
ZSE
KSL
5
Taking all (or certain) columns to consider the unique value.
Both of the scenario above can be achieved in query without the need to alter the table, adding and populate a new column but of course, the latter is also possible.
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)
I am using the INSERT OR REPLACE syntax to either insert or update a row that may exist based on a unique column constraint within the table.
The table structure is
| Name | Age | CustomerId (unique) |
When I print out the table the first time, I get something like
| Name | Age | CustomerId | rowid |
|"Bob" | 22 | 5 | 1 |
Then I run INSERT OR REPLACE INTO MyTable(Name, Age, CustomerId) VALUES ("Bob", 23, 5);"
Without fail, this will increment the rowid column each time it is run. So now the result is
| Name | Age | CustomerId | rowid |
|"Bob" | 23 | 5 | 2 |
How do I prevent rowid from incrementing?
This is how INSERT OR REPLACE works.
If a violation of a unique index/constraint occurs then the existing row is deleted and the new row is inserted, so a new rowid is assigned for the new row.
If you don't want this to happen you must use UPSERT:
insert into tablename(Name, Age, CustomerId) values ('Bob', 23, 5)
on conflict(CustomerId) do update
set Name = excluded.Name,
Age = excluded.Age;
See the demo.
Consider that my SQLite table has the following schema,
|'''''''''''''''''''''''''''''''''''''
| unique_id(TXT) | object_data(BLOB) |
|'''''''''''''''''''''''''''''''''''''
| | |
| | |
| | |
''''''''''''''''''''''''''''''''''''''
Assume that the row_id property is enabled, and so my question is, for a given unique_id, is it possible to fetch the next 50 records from the table,
using a single SQL query? (Using the row_id property)
Try getting result through this method.
Select * from table_name [WHERE conditions] Limit 50 offset (Select row_id from table_name where unique_id = x);
I have this database in sqlite (table1):
+-----+-------+-------+
| _id | name | level |
+-----+-------+-------+
| 1 | Mike | 3 |
| 2 | John | 2 |
| 3 | Bob | 2 |
| 4 | David | 1 |
| 5 | Tom | 2 |
+-----+-------+-------+
I want to create a view with all elements of level 2 and then to add a new column indicating the order of the row in the new table. That is, I would want this result:
+-------+------+
| index | name |
+-------+------+
| 1 | John |
| 2 | Bob |
| 3 | Tom |
+-------+------+
I have tried:
CREATE VIEW words AS SELECT _id as index, name FROM table1;
But then I get:
+-------+------+
| index | name |
+-------+------+
| 2 | John |
| 3 | Bob |
| 5 | Tom |
+-------+------+
I suppose it should be something as:
CREATE VIEW words AS SELECT XXXX as index, name FROM table 1;
What should I use instead of XXXX?
When ordered by _id, the number of rows up to and including this one is the same as the number of rows where the _id value is less than or equal to this row's _id:
CREATE VIEW words AS
SELECT (SELECT COUNT(*)
FROM table1 b
WHERE level = 2
AND b._id <= a._id) AS "index",
name
FROM table1 a
WHERE level = 2;
(The computation itself does not actually require ORDER BY _id because the order of the rows does not matter when we're just counting them.)
Please note that words is not guaranteed to be sorted; add ORDER BY "index" if needed.
And this is, of course, not very efficient.
You have two options. First, you could simply add a new column with the following:
ALTER TABLE {tableName} ADD COLUMN COLNew {type};
Second, and more complicatedly, but would actually put the column where you want it, would be to rename the table:
ALTER TABLE {tableName} RENAME TO TempOldTable;
Then create the new table with the missing column:
CREATE TABLE {tableName} (name TEXT, COLNew {type} DEFAULT {defaultValue}, qty INTEGER, rate REAL);
And populate it with the old data:
INSERT INTO {tableName} (name, qty, rate) SELECT name, qty, rate FROM TempOldTable;
Then delete the old table:
DROP TABLE TempOldTable;
I'd much prefer the second option, as it will allow you to completely rename everything if need be.