Constraints about - constraints

What constraints are copied with table when we create table by using create table as select statement..?

I don't know about MySQL, but - as of Oracle - only the NOT NULL constraint. Even if there was a column designed as a primary key (which - implicitly - means that it can't be NULL), newly created table won't have that constraint.
For example:
SQL> create table test_1
2 (id number primary key,
3 name varchar2(20) not null);
Table created.
SQL> select constraint_name, constraint_Type from user_constraints where table_name = 'TEST_1';
CONSTRAINT_NAME C
-------------------- -
SYS_C009194 C --> "C"heck (NOT NULL) constraint
SYS_C009195 P --> "P"rimary key constraint
SQL> create table test_2 as select * from test_1;
Table created.
SQL> select constraint_name, constraint_Type from user_constraints where table_name = 'TEST_2';
CONSTRAINT_NAME C
-------------------- -
SYS_C009196 C --> that's the "C"heck - NOT NULL constraint
SQL> desc test_2
Name Null? Type
----------------------------------------- -------- ----------------------------
ID NUMBER
NAME NOT NULL VARCHAR2(20)
SQL>

MySQL would only preserve NOT NULL as constarint
CREATE TABLE tab1(id int AUTO_INCREMENT PRIMARY KEY)
create table tab2
(id int primary key,
col1 varchar(20) not null,
col2 int UNIQUE,
col3 int, FOREIGN KEY (col3) REFERENCES tab1(id))
CREATE TABLE tab3 AS SELECT * FROM tab2
Records: 0 Duplicates: 0 Warnings: 0
SHOW CREATE TABLE tab3
Table
Create Table
tab3
CREATE TABLE `tab3` (  `id` int NOT NULL,  `col1` varchar(20) NOT NULL,  `col2` int DEFAULT NULL,  `col3` int DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
fiddle

Related

MARIADB sequences - incrementing by 2

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.

SQLite3 run a trigger insert multiple times besed on inserted vlaue

Want to run an insert n-times, the n is defined by inserted value on another table.
table 1:
create table Table1
(
id INTEGER default 1 not null
primary key
unique,
name TEXT not null
unique,
keys_number INTEGER default 1 not null
);
table 2:
create table table_2
(
id INTEGER default 1 not null
primary key
unique,
table_1_id INTEGER not null
references table_1,
);
Now when i insert into table_1 like:
INSERT INT table_1 (name, keys_number) VALUES ('dummy_name', 5)
want to run a trigger
CREATE TRIGGER insert_keys_after_insert_table_1
AFTER INSERT ON table_1
WHEN (SELECT COUNT(*) FROM table_2 WHERE table_1_id=new.id) < new.keys_number
BEGIN
INSERT INTO keys (table_1_id) VALUES (new.id);
END;
But this runs only once.
Finally, I want to have on table_2 values after the trigger
INSERT INT table_1 (name, keys_number) VALUES ('dummy_name_1', 5)
make the result like:
id;name;keys_number
1;dummy_name_1;5
and the result on table_2 after the trigger, should be
id;table_1_id
1;1
2;1
3;1
4;1
5;1
or if I insert another one on table_1
INSERT INT table_1 (name, keys_number) VALUES ('dummy_name_2', 2)
will make the result on table_1 like:
id;name;keys_number
1;dummy_name_1;5
2;dummy_name_2;2
and the trigger will give the result on table_2:
id;table_1_id
1;1
2;1
3;1
4;1
5;1
6;2
7;2
For this requirement you need a loop, which in SQL is implemented via a recursive CTE.
Unfortunately SQLite does not allow CTEs inside a trigger.
A workaround is to create a new table with only 1 column which will store the numbers 1 to the max expected value of keys_number in table_1:
CREATE TABLE table_numbers AS
WITH cte(keys_number) AS (
SELECT 1
UNION ALL
SELECT keys_number + 1 FROM cte WHERE keys_number < 100 -- change 100 to the max keys_number you expect
)
SELECT keys_number FROM cte
Now you can create your trigger:
CREATE TRIGGER insert_keys_after_insert_table_1 AFTER INSERT ON table_1
BEGIN
INSERT INTO table_2(table_1_id)
SELECT NEW.id
FROM table_numbers
WHERE keys_number <= NEW.keys_number - (SELECT COUNT(*) FROM table_2 WHERE table_1_id = NEW.id);
END;
See the demo.

How to move column from referenced table to referrer table using only SQLite language dialect?

I have following table structure in SQLite database:
CREATE TABLE A (id integer primary key, name text, room Integer);
CREATE TABLE B (id integer primary key, idA integer not null, code blob, FOREIGN KEY(idA) REFERENCES A(id));
For each record in A there are 1 to n records in B that refers it. Desired table structure is:
CREATE TABLE A (id integer primary key, name text);
CREATE TABLE B (id integer primary key, idA integer not null, code blob, room Integer, FOREIGN KEY(idA) REFERENCES A(id));
So, I would like to transer room column from A to B without data loss: recreate table A without room column, delete duplicates from A, add room column to B, set it depends on what values were in referenced A records room columns (original A table) and reassign idA for B records.
Is it possible using only SQLite and if it is, how to do this, using only SQLite?
Thank you!
have a look at http://sqlfiddle.com/#!5/e26e2/1 .
creating the databases :
CREATE TABLE A (id integer primary key, name text, room Integer);
CREATE TABLE B (id integer primary key, idA integer not null, code blob, FOREIGN KEY(idA) REFERENCES A(id));
Fill in some test data :
insert into A (id, name, room) values (1, "azerty", 123) ;
insert into A (id, name, room) values (2, "querty", 456) ;
insert into B (id, idA, code) values (10, 1, "code 1") ;
insert into B (id, idA, code) values (15, 1, "code 1b") ;
insert into B (id, idA, code) values (20, 1, "code 1c") ;
insert into B (id, idA, code) values (25, 2, "code 2") ;
insert into B (id, idA, code) values (30, 3, "code 3") ;
copy the wrong table layouts to tables we will later drop :
alter table B rename to old_B ;
alter table A rename to old_A ;
Create tables according the correct layout :
CREATE TABLE A (id integer primary key, name text);
CREATE TABLE B (id integer primary key, idA integer not null, code blob, room Integer, FOREIGN KEY(idA) REFERENCES A(id));
Copy selected data from old_A into A :
INSERT OR REPLACE INTO A ( id, name)
SELECT id, name FROM old_A ;
fill B with an inner join to "line up" room with correct idA :
INSERT OR REPLACE INTO B ( id, idA, code, room)
SELECT old_B.*, old_A.room FROM old_B INNER JOIN old_A ON old_B.idA = old_A.id ;
drop the old tables
DROP TABLE old_A ;
DROP TABLE old_B ;

Oracle: object relational database, how to insert table values with foreign key?

Actually, I have two tables Branch and Account_table and I want to insert the account_table values with a foreign key(bID) values which is primary key in Branch Table (bID) but I am getting errors while inserting values. Following is my code.
create type bank_branch as object(
bID varchar2(10),
street varchar2(20),
city varchar2(20),
zipcode varchar2(10),
bPhone varchar2(20))
not final
/
create table branch of bank_branch(
primary key (bID),
/
insert into branch values(
'601','XYZ Street','Orlando','OR112AB','024771169');
/
insert into branch values(
'620','Terrace Road','California','CL229JH','548711131');
/
insert into branch values(
'630','Miami Street','Miami','M21334A','9665411211');
/
create type account_type as object(
accNum int,
accType varchar2(15),
balance number,
bID varchar2(10),
interest number,
overdraftLimit number,
openDate DATE)
/
create table account_table of account_type(
primary key (accNum),
FOREIGN key (bID) REFERENCES branch(bID));
/
insert into account_table
select 'bID', b.BID
from branch b
where b.BID = 601,
'1001','current','630.87','0.009','400','10-Sep-14');
/
Thanks.
create type bank_branch as object(
bID varchar2(10),
street varchar2(20),
city varchar2(20),
zipcode varchar2(10),
bPhone varchar2(20))
not final
/
create table branch of bank_branch(
primary key (bID));
/
insert into branch values(
'601','XYZ Street','Orlando','OR112AB','024771169');
/
insert into branch values(
'620','Terrace Road','California','CL229JH','548711131');
/
insert into branch values(
'630','Miami Street','Miami','M21334A','9665411211');
/
create type account_type as object(
accNum int,
accType varchar2(15),
balance number,
bID varchar2(10),
interest number,
overdraftLimit number,
openDate DATE);
/
create table account_table of account_type(
primary key (accNum),
FOREIGN key (bID) REFERENCES branch(bID));
/
insert into account_table
select '1001','current','630.87',b.BID,'0.009','400','10-Sep-14'
from branch b
where b.BID = 601;
/
1 row(s) inserted.
I have used the same code as yours. Only the insert statement differs. It works fine for me.

Oracle PLSQL update table where in Associative Array?

I would like to, in a stored proc, update all the records that match an id.
Now, this list of id, is being passed in as a table of varchar (Associative Array)..
CREATE TYPE varcharArray AS TABLE OF VARCHAR2(1000) index by ...
and the proc declaration is something like
PROCEDURE testProc (p_IDs in varcharArray, p_Success out Number)
and the update statement in the proc
update testtable
set col = 'val'
where id in (select column_value from table(p_IDs);
This doesn't seem to work. So i had to do a loop in the array and update for each Id.
But i'd really like it to update using the where in clause.. Any help would be great.
PS: the id field is a number.
It works for me:
create table testtable (col varchar2(10), id varchar2(1000));
insert into testtable values (null, 'AAA');
insert into testtable values (null, 'BBB');
insert into testtable values (null, 'CCC');
insert into testtable values (null, 'DDD');
commit;
create or replace PROCEDURE testProc (p_IDs in varcharArray) is
begin
update testtable
set col = 'val'
where id in (select column_value from table(p_IDs));
end;
/
exec testproc(p_ids=>varcharArray('AAA','DDD'));
SQL> select * from testtable;
COL ID
---------- ----------
val AAA
BBB
CCC
val DDD

Resources