Current table questions:
rowid: 1 | 2 | 3 | 4 | 5
id: 3 | 4 | 7 | 9 | 10
Trying to achieve the following:
rowid: 1 | 2 | 3 | 4 | 5
id: 1 | 2 | 3 | 4 | 5
I have tried many different variations of SQL without success, this is the latest I am testing:
UPDATE questions SET id = rowid;
Can someone please suggest how I solve this as I have googled and cannot find the solution?
I don't believe that your question completely encompasses all aspects of the issue.
In theory to have a table (the before table) where SELECT rowid, id results in
rowid: 1 | 2 | 3 | 4 | 5
id: 3 | 4 | 7 | 9 | 10
The id column must not be an alias of the rowid column (otherwise the values would be identical)
However, if the id column is an alias of the rowid column, the both columns would be the same so the before table above would not be as above.
As an example using :-
--<<<<<<<<<< WORKS >>>>>>>>>>
-- as ID is not an alias of the rowid column update changes id column
DROP TABLE IF EXISTS questionsv3;
CREATE TABLE IF NOT EXISTS questionsv3 (ID INTEGER);
INSERT INTO questionsv3 VALUES (3),(4),(7),(9),(10);
SELECT rowid, id FROM questionsv3;
UPDATE questionsv3 SET id = rowid;
SELECT rowid, id FROM questionsv3;
results in the expected result as per :-
First Select (before update) :-
Second Select (after update)
Other potential causes
rowid is not in fact the rowid as per SQLITE, but a conceptual idea that it should be 1,2,3 ...... (in which case using VACUUM, if there is no alias to the rowid, may result in the desired re-numbering of the rowid column, which if followed by the update may then result in the id being re-sequenced).
That the update is done within a transaction that hasn't been committed and is rolled back.
You may wish to consider the following permutations of different table creations (see comments) :-
-- as ID is an alias of rowid, then rowid is set according to ID so update does nothing
DROP TABLE IF EXISTS questionsv1;
CREATE TABLE IF NOT EXISTS questionsv1 (ID INTEGER PRIMARY KEY);
INSERT INTO questionsv1 VALUES (3),(4),(7),(9),(10);
SELECT rowid, id FROM questionsv1;
UPDATE questionsv1 SET id = rowid;
SELECT rowid, id FROM questionsv1;
-- as ID is an alias of the rowid column, then rowid is set according to the ID so update does nothing
DROP TABLE IF EXISTS questionsv2;
CREATE TABLE IF NOT EXISTS questionsv2 (ID INTEGER PRIMARY KEY AUTOINCREMENT);
INSERT INTO questionsv2 VALUES (3),(4),(7),(9),(10);
SELECT rowid, id FROM questionsv2;
UPDATE questionsv2 SET id = rowid;
SELECT rowid, id FROM questionsv2;
--<<<<<<<<<< WORKS >>>>>>>>>>
-- as ID is not an alias of the rowid column update changes id column
DROP TABLE IF EXISTS questionsv3;
CREATE TABLE IF NOT EXISTS questionsv3 (ID INTEGER);
INSERT INTO questionsv3 VALUES (3),(4),(7),(9),(10);
SELECT rowid, id FROM questionsv3;
UPDATE questionsv3 SET id = rowid;
SELECT rowid, id FROM questionsv3;
--<<<<<<<<<< WORKS >>>>>>>>>>
-- as ID is not an alias of rowid the ID column is updated accordingly
DROP TABLE IF EXISTS questionsv4;
CREATE TABLE IF NOT EXISTS questionsv4 (ID TEXT PRIMARY KEY); -- not an alias of rowid
INSERT INTO questionsv4 VALUES (3),(4),(7),(9),(10);
SELECT rowid, id FROM questionsv4;
UPDATE questionsv4 SET id = rowid;
SELECT rowid, id FROM questionsv4;
--<<<<<<<<<< FAILS >>>>>>>>>>
DROP TABLE IF EXISTS questionsv13;
CREATE TABLE IF NOT EXISTS questionsv13 (ID INTEGER PRIMARY KEY) WITHOUT ROWID;
INSERT INTO questionsv13 VALUES (3),(4),(7),(9),(10);
SELECT id FROM questionsv13;
UPDATE questionsv13 SET id = rowid; -- would fail no such column
SELECT id FROM questionsv13;
Related
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.
I would like to populate a freshly created Table in a SQLite DB.
In this table, some keys are references to other tables and I'd like not to hard-code these references
-> I'm currently using a "mapping" table in order to fetch ids using names (~ constants emulation)
The problem is: this solution works but is very verbose
Minimal working example: (storing dictionary words, using foreign keys to a category table)
-- Tables creation
CREATE TABLE categories(
id INTEGER PRIMARY KEY,
name TEXT
);
CREATE TABLE words(
id INTEGER PRIMARY KEY,
id_category INTEGER NOT NULL,
name TEXT,
FOREIGN KEY(id_category) REFERENCES categories(id)
);
CREATE TABLE CONSTANTS(
name TEXT PRIMARY KEY,
value INTEGER NOT NULL
);
INSERT INTO categories(name) VALUES("noun");
INSERT INTO CONSTANTS(name, value) VALUES("category_noun", last_insert_rowid());
INSERT INTO categories(name) VALUES("abreviation");
INSERT INTO CONSTANTS(name, value) VALUES("category_abreviation", last_insert_rowid());
INSERT INTO categories(name) VALUES("character");
INSERT INTO CONSTANTS(name, value) VALUES("category_character", last_insert_rowid());
And now, the core of the problem: too much verbose.
In this example is only one foreign key, a few insert to illustrate the problem
INSERT INTO words(id_category, name) VALUES
((SELECT value FROM CONSTANTS WHERE name = "category_noun"),
"hello"),
((SELECT value FROM CONSTANTS WHERE name = "category_abreviation"),
"SO"),
((SELECT value FROM CONSTANTS WHERE name = "category_abreviation"),
"user"),
((SELECT value FROM CONSTANTS WHERE name = "category_character"),
"!")
;
I would like to have something looking like this pseudo-sqlite code:
-- same table creations as before
INSERT INTO words(id_category, name) VALUES
-- Fetch constants once
CAT_NOUM = SELECT value FROM CONSTANTS WHERE name = "category_noum"),
CAT_ABREV = SELECT value FROM CONSTANTS WHERE name = "category_abreviation"),
CAT_CHAR = SELECT value FROM CONSTANTS WHERE name = "category_abreviation")
)
-- Fill the table, using constants
(CAT_NOUM, "Hello"),
(CAT_ABREV, "SO"),
(CAT_NOUM, "user"),
(CAT_CHAR, "SO"),
...
;
I'm wondering if
There is already a SQLite solution to this problem
I should use something like sed to replace a hard-coded string like __SED__CAT_NOUM with its greped value in the SQLite script
Doing this stuff programmatically would be the right way
It is better to use INSERT...SELECT with UNION ALL instead of INSERT...VALUES:
INSERT INTO words(id_category, name)
SELECT value, 'hello' FROM CONSTANTS WHERE name = 'category_noun' UNION ALL
SELECT value, 'SO' FROM CONSTANTS WHERE name = 'category_abreviation' UNION ALL
SELECT value, 'user' FROM CONSTANTS WHERE name = 'category_abreviation' UNION ALL
SELECT value, '!' FROM CONSTANTS WHERE name = 'category_character';
See the demo.
Or use Row Values to join to CONSTANTS:
INSERT INTO words(id_category, name)
SELECT c.value, t.column2
FROM CONSTANTS C INNER JOIN (
VALUES ('category_noun', 'hello'),
('category_abreviation', 'SO'),
('category_abreviation', 'user'),
('category_character', '!')
) t ON t.column1 = c.name;
See the demo.
Results:
SELECT * FROM words;
| id | id_category | name |
| --- | ----------- | ----- |
| 1 | 1 | hello |
| 2 | 2 | SO |
| 3 | 2 | user |
| 4 | 3 | ! |
I have a table of ratings
|EMPLOYEE|Rating|
1 B
2 B
3 C
4 NULL
5 NULL
6 NULL
and i want to retrieve the count of the grades by each grading like so
Result set
|Rating|Count|
A 0
B 2
C 1
D 0
E 0
I used this query but the grades that isnt in the table will jsut appear as null
select rating,count(rating) from table group by rating
I also used this query which is basically a pivot of the above result set but for some reason it shows 3 rows of repeating data instead of just 1
select (select count(rating) from table where rating = 'E'),(select count(rating) from table where rating = 'D'),(select count(rating) from table where rating = 'C'),(select count(rating) from table where rating = 'B'),(select count(rating) from table where rating = 'A') from table group by rating
If you had a table for the assignable ratings then it would be quite simple (and flexible)
e.g. consider :-
Your existing table.
DROP TABLE IF EXISTS mytable;
CREATE TABLE IF NOT EXISTS mytable (employee TEXT, rating text);
INSERT INTO mytable VALUES (1,'B'),(2,'B'),(3,'C'),(4,null),(5,null),(6,null);
The rating table.
DROP TABLE IF EXISTS rating;
CREATE TABLE IF NOT EXISTS rating (rating);
INSERT INTO rating VALUES('A'),('B'),('C'),('D'),('E');
Then :-
SELECT rating.rating, (SELECT count(*) FROM mytable WHERE rating.rating = mytable.rating) FROM rating;
Results in :-
Flexibility
Add some new ratings e.g. as per :-
INSERT INTO rating VALUES('X'),('Y'),('Z');
And then run:--
SELECT rating.rating, (SELECT count(*) FROM mytable WHERE rating.rating = mytable.rating) FROM rating;
results in :-
I have two tables whose relevant columns look more or less like the following:
table1.id:
zIXuJeY-qH
zJrcULGLXK
zXyIgnlylb
zZ7MYDGDAV
zbCFI4wKpe
ziGeauO-0O
zmzWbaGSb7
table2.id
zIXuJeY-qH
zIXuJeY-qH
zIXuJeY-qH
zIXuJeY-qH
zJrcULGLXK
zJrcULGLXK
in which table1.id is a primary key and table2.id is not a primary key. I'm trying to grab all the IDs from table 1 that are not in table 2, but am having trouble. If, for instance, I select a count of all the values that are in table two, I get:
>SELECT COUNT(id) FROM table1 WHERE id IN (SELECT id FROM table2);
>2
But if I try to find the IDs not in table2, I get 0:
>SELECT COUNT(id) FROM table1 WHERE id NOT IN (SELECT id FROM table2);
>
There are 503 unique IDs in table1 and only 163 in table2. What am I doing wrong?
I suppose there can be nulls in table2.id?
NOT IN ( ..., null, ...)
does never result in true unfortunately (because - so the argumentation - null is the unknown value, and we cannot guarantee that the unknown value is not the value you are looking for obviously). A bad trap.
Try
SELECT COUNT(id) FROM table1 WHERE id NOT IN (SELECT id FROM table2 where id is not null);
or an EXISTS clause instead.
Example:
It does not work.
UPDATE column_name SET rownum FROM table_name
This work!
UPDATE table_name SET column_name = rownum;
This works but the update is performed incorrectly
SELECT * FROM table_name ORDER BY column_name;
UPDATE table_name SET column_name = rownum;
I wish the following update behavior:
Note:'rownum ' It is not a physical column of the table
/*
pc_comentario = tableName
cod_comentario = columnName (Reference column for sorting)
dtc_andamento = columnDay (Reference column to update the "columnName" according to the order of this column)
*/
rownum | columnName | columnDay
1 1 day 1
2 5 day 5
3 7 day 2
After change with update
rownum | columnName (Update this column) | columnDay (sort by this column)
1 1 day 1
2 2 day 2
3 3 day 5
ALMOST DONE! this column 'cod_comentario_1 "which was materialized in RAM is correct. I need this column" cod_comentario_1 "that does not exist in the table is acknowledged in the consultations with java.
SELECT cod_comentario, dtc_andamento, cod_processo ,
ROW_NUMBER()
OVER (PARTITION BY cod_processo
ORDER BY dtc_andamento) cod_comentario_1
FROM pc_comentario
upadate do not work this way:
UPDATE (
SELECT cod_processo
ROW_NUMBER()
OVER (PARTITION BY cod_processo
ORDER BY dtc_andamento)cod_comentario_1
FROM pc_comentario
) SET cod_comentario_1)
order by Seq
I must enter the values of this consultation in a new column that I created
SELECT
ROW_NUMBER()
OVER (PARTITION BY cod_processo
ORDER BY dtc_andamento DESC)
FROM pc_comentario
Try:
UPDATE table_name
SET column_name = rownum
Shouldn't it be like below rather; I believe UPDATE statement has no FROM clause
UPDATE table_name SET column_name = rownum;
Again, it will work only if rownum is an existing column in your table. If you are trying to use Oracle rownum instead then consider using row_number() function rather
update table_name set column_name =
select rn from ( select column_name, row_number() over (order by column_name) rn
from table_name ) xx;
As you state yourself, rownum is a virtual column. It assigns a sequential value to each row of a particular result set. Which means that the row number of a row could be completely different in the result set of a different query.
If you really want to show the row number as part of the result set, specify it as you would any column:
select rownum as columnName, columnDay
from table
order by ...;