add a primary key to new table created by query result - sql

I want to create a table using query result. But I want to also add a auto increment primary key field to it. Is it possible to achieve it using SQLite?
Example:
Select two fields from table_a. But I want the output schema as (id, field_a, field_b).
create table foo as
select field_a, field_b
from tablel_a
Currently using SQLite 3, but solutions using other database systems are also fine.

This is not possible with a single statement; CREATE TABLE ... AS ... does not create constraints.
You have to use two statements:
CREATE TABLE foo ( ID INTEGER PRIMARY KEY, [...] );
INSERT INTO foo (...) SELECT ...;

by default sqlite adds a rowid column in every table you create , so unless there's some specific need here, you can use this rowid column
check this out https://www.sqlite.org/lang_createtable.html#rowid

Related

Oracle SQL: "GENERATED ALWAYS" with a specified sequence

I have two tables that I would like to let them share the same sequence to populate the primary key ID column. However, I also don't want the user to specify or change the value for the ID column.
By using the code below, I can let two tables share the same sequence.
CREATE TABLE T1
(
ID INTEGER DEFAULT SEQ_1.nextval NOT NULL
);
This code will use its own sequence and prevent users from changing or specifying with INSERT:
CREATE TABLE T1
(
ID INTEGER GENERATED ALWAYS AS IDENTITY NOT NULL
);
Is there a way that can both world? Something like this:
CREATE TABLE T1
(
ID INTEGER GENERATED ALWAYS AS ( SEQ_1.nextval ) NOT NULL
);
Regarding the use case, as #Sujitmohanty30 asked, the reason that I raised this question:
I'm thinking to implement inheritance in the database, consider this UML diagram (I can't directly post images due to insufficient reputation, and sorry for being lack of imagination).
ANIMAL is abstract and all inheritance is mandatory. This means no instance of ANIMAL should be created. Furthermore, there is an one-to-many relationship between ANIMAL and ZOO_KEEPER.
Therefore, I came up with this idea:
CREATE SEQUENCE ANIMAL_ID_SEQ;
CREATE TABLE HORSE
(
ID INT DEFAULT ANIMAL_ID_SEQ.nextval NOT NULL PRIMARY KEY,
HEIGHT DECIMAL(3, 2) NOT NULL
);
CREATE TABLE DOLPHIN
(
ID INT DEFAULT ANIMAL_ID_SEQ.nextval NOT NULL PRIMARY KEY,
LENGTH DECIMAL(3, 2) NOT NULL
);
CREATE MATERIALIZED VIEW LOG ON HORSE WITH ROWID;
CREATE MATERIALIZED VIEW LOG ON DOLPHIN WITH ROWID;
CREATE MATERIALIZED VIEW ANIMAL
REFRESH FAST ON COMMIT
AS
SELECT 'horse' AS TYPE, ROWID AS RID, ID -- TYPE column is used as a UNION ALL marker
FROM HORSE
UNION ALL
SELECT 'dolphin' AS TYPE, ROWID AS RID, ID
FROM DOLPHIN;
ALTER TABLE ANIMAL
ADD CONSTRAINT ANIMAL_PK PRIMARY KEY (ID);
CREATE TABLE ZOO_KEEPER
(
NAME VARCHAR(50) NOT NULL PRIMARY KEY,
ANIMAL_ID INT NOT NULL REFERENCES ANIMAL (ID)
);
In this case, the use of the shared sequence is to avoid collision in ANIMAL mview. It uses DEFAULT to get the next ID of the shared sequence. However, using DEFAULT doesn't prevent users from manually INSERTing the ID field or UPDATE the value of it.
You can create a master view/table and generate the sequence in it.
Then copy it as column values into both tables while inserting.
Another option could be inserting into both tables at same time.Use SEQ.NEXTVAL to insert into first table to get a new ID, and then SEQ.CURRVAL to copy same id in the table.
No, you cant have anything like this because ID is independently generated for each of the tables and this can be done only using sequence when you are inserting the data in both the tables at the same time.
You should normalize your data schema: add column animal_type into the table and create composite primary key on both columns

H2 Database - Reorder columns using SQL

I have a H2 database with 16 million entries and no primary key. I successfully added an auto-incrementing primary key using the following statements:
ALTER TABLE
PUBLIC.ADDRESSES ADD ID BIGINT AUTO_INCREMENT;
ALTER TABLE
PUBLIC.ADDRESSES ADD PRIMARY KEY (ID)
Now the problem is, that the column order is STREET, HOUSENUMBER, ..., ID, but I would like ID to be the first column of the table. It looks like there is a corresponding ALTER TABLE statement MySQL (see here), but I'm unable to adapt it to H2.
Long story short: How can I change the column order to ID, STREET, HOUSENUMBER ...? Is there a solution similar to:
ALTER TABLE "ADDRESSES" MODIFY COLUMN "ID" BEFORE "STREET";
Any help is kindly appreciated.
H2 does not currently support re-ordering columns. You would need to run multiple statements:
First, rename the column, then add a new column with the right name at the right position (alter table add supports positioning), and finally drop the old column.
Or, probably more elegant, use rename table and then create table ... as select.

Insert or replace in SQLite

I want to insert or replace in SQLite by 2 fields Varchar and Integer. These 2 fields should be unique. So i have to create special table with 2 fields as unique ?
Maybe some one could help on this.
If you want the combination of two fields to be unique, the easiest way is to create a unique index on these fields:
CREATE UNIQUE INDEX field1_field2_idx ON table_name(field1, field2)
then in case of a conflict the INSERT OR REPLACE statement will replace the existing record with the new one.

CREATE TABLE AS - how to add column with PK?

I have to create a table (H2 embedded database) using fields from other tables. I decided to use CREATE TABLE AS statement.
My code:
CREATE TABLE DOC AS
SELECT I.ID, I.STATUS, A.REMINDERINFORMATION
FROM IE802 I JOIN IE802_ATTRIBUTES A ON A.IE802_ID=I.ID;
Each row which is generated from the code above additionally must have DOCID PrimaryKey. How can I add this column and make it autoincrement and PK at the same time?
Thanks for any tips and other solutions!
Alternatively, how can I make existing I.ID to be PK?
I'm still getting an error: Column "ID" must not be nullable; SQL statement:
ALTER TABLE DOC ADD PRIMARY KEY (ID) [90023-147]
H2 supports column definitions in CREATE AS SELECT:
CREATE TABLE DOC(
ID INT PRIMARY KEY,
STATUS INT,
REMINDERINFORMATION VARCHAR(255)
)
AS SELECT I.ID, I.STATUS, A.REMINDERINFORMATION
FROM IE802 I JOIN IE802_ATTRIBUTES A ON A.IE802_ID=I.ID;

How to insert duplicate rows in SQLite with a unique ID?

This seems simple enough: I want to duplicate a row in a SQLite table:
INSERT INTO table SELECT * FROM table WHERE rowId=5;
If there were no explicit unique column declarations, the statement would work, but the table's first column is declared rowID INTEGER NOT NULL PRIMARY KEY. Is there any way to create a simple statement like the one above that works without knowing the schema of the table (aside from the first column)?
This can be done using * syntax without having to know the schema of the table (other than the name of the primary key). The trick is to create a temporary table using the "CREATE TABLE AS" syntax.
In this example I assume that there is an existing, populated, table called "src" with an INTEGER PRIMARY KEY called "id", as well as several other columns. To duplicate the rows of "src", use the following SQL in SQLite3:
CREATE TEMPORARY TABLE tmp AS SELECT * FROM src;
UPDATE tmp SET id = NULL;
INSERT INTO src SELECT * FROM tmp;
DROP TABLE tmp;
The above example duplicates all rows of the table "src". To only duplicate a desired row, simply add a WHERE clause to the first line. This example works because the table "tmp" has no primary key constraint, but "src" does. Inserting NULL primary keys into src causes them to be given auto-generated values.
From the sqlite documentation: http://www.sqlite.org/lang_createtable.html
A "CREATE TABLE ... AS SELECT" statement creates and populates a database table based on the results of a SELECT statement. A table created using CREATE TABLE AS has no PRIMARY KEY and no constraints of any kind.
If you want to get really fancy, you can add a trigger that updates a third table which maps old primary keys to newly generated primary keys.
No. You need to know the schema of the table to write the insert statement properly.
You need to be able to write the statement in the form of:
insert into Table (column1, column2, column3)
select column1, column2, column3
from OtherTable
where rowId = 5
Well, since I was unable to do this the way I wanted, I resorted to using the implicit row id, which handily enough has the same name as the rowId column I defined explicitly, so now I can use the query I had in the question, and it will insert all the data with a new rowId. To keep the rest of the program working, I just changed SELECT * FROM table to SELECT rowId,* FROM table and everything's fine.
Absolutely no way to do this. Primary Key declaration implies this field is unique. You can't have a non unique PK. There is no way to create a row with existing PK in the same table.