Not expected result of the query - sql

There is a query:
select * from
(
select
p.ID
from
MY_PRODUCT_PARENT_LINK pLink
inner join MY_PRODUCT p on pLink.FK_PARENT=p.ID
order by
pLink.DESCENDANT_LVL desc
)
where rownum <= 1
;
The inner query returns one row with not null value of p.ID.
The outer query - one row with null value of p.ID. Here expected not null value.
The database sever is Oracle 11g.
There is a code to reproduction:
CREATE TABLE MY_PRODUCT
(
FK_PARENT NUMBER(19),
ID NUMBER(19) NOT NULL,
NAME VARCHAR2(4000 BYTE),
CONSTRAINT PK_MY_PRODUCT PRIMARY KEY (ID)
);
INSERT INTO MY_PRODUCT (FK_PARENT, ID,NAME) VALUES (null, 111111,'PRODUCT_NAME_01');
INSERT INTO MY_PRODUCT (FK_PARENT, ID,NAME) VALUES (null, 111112,'PRODUCT_NAME_02');
CREATE TABLE MY_PRODUCT_PARENT_LINK
(
ID NUMBER(19) NOT NULL,
FK_PRODUCT NUMBER(19) NOT NULL,
FK_PARENT NUMBER(19) NOT NULL,
DESCENDANT_LVL NUMBER(19) NOT NULL,
primary key (ID)
);
ALTER TABLE MY_PRODUCT_PARENT_LINK ADD
CONSTRAINT MY_PRD_PARENT_TO_MY_PRODUCT
FOREIGN KEY (FK_PRODUCT)
REFERENCES MY_PRODUCT (ID) ON DELETE CASCADE;
ALTER TABLE MY_PRODUCT_PARENT_LINK ADD
CONSTRAINT MY_PRD_PARENT_TO_PARENT
FOREIGN KEY (FK_PARENT)
REFERENCES MY_PRODUCT (ID) ON DELETE CASCADE;
INSERT INTO MY_PRODUCT_PARENT_LINK (ID, FK_PRODUCT, FK_PARENT, DESCENDANT_LVL) VALUES (211111, 111112, 111111, 1);

Try and select the ID in the outer query and see if that returns the result. so instead of select * in the outer do select ID.

Related

Counting in Oracle 11g

all day I am struggling with oracle exrcises and again I stuck. I need to select last names of boxers with their wins of each weight category.
So I have:
table "boxer" with columns: id, fname, lname, weight
table "fight" with two foreign keys from table boxer (id_boxer1 and id_boxer2) and with one column winner (if boxer1 won then winner will be number 1, if boxer2 won then winner will be number 2)
table "category_weight" with columns: id, min_weight, max_weight, name (of a category)
Example:
CREATE TABLE category_weight(
id INTEGER NOT NULL,
min_weight SMALLINT NOT NULL,
max_weight SMALLINT NOT NULL,
name VARCHAR2(20) NOT NULL
);
ALTER TABLE category_weight ADD CONSTRAINT category_weight_pk PRIMARY KEY ( id );
CREATE TABLE boxer(
id INTEGER NOT NULL,
fname VARCHAR2(20) NOT NULL,
lname VARCHAR2(20) NOT NULL,
weight INTEGER NOT NULL
);
ALTER TABLE boxer ADD CONSTRAINT boxer_pk PRIMARY KEY ( id );
CREATE TABLE fight(
id INTEGER NOT NULL,
winner SMALLINT NOT NULL,
id_category_weight INTEGER NOT NULL,
id_boxer1 INTEGER NOT NULL,
id_boxer2 INTEGER NOT NULL
);
ALTER TABLE fight ADD CONSTRAINT fight_pk PRIMARY KEY ( id );
ALTER TABLE fight
ADD CONSTRAINT boxer_fk FOREIGN KEY ( id_boxer1 )
REFERENCES boxer ( id );
ALTER TABLE fight
ADD CONSTRAINT boxer_fk2 FOREIGN KEY ( id_boxer2 )
REFERENCES boxer ( id );
ALTER TABLE fight
ADD CONSTRAINT categ_weight_fk FOREIGN KEY ( id_category_weight )
REFERENCES category_weight ( id );
INSERT INTO boxer
VALUES ('1', 'Johnny','Johnny','60');
INSERT INTO boxer
VALUES ('2', 'Anthonny','Anthonny','54');
INSERT INTO boxer
VALUES ('3', 'Anonimm','Anonimm','59');
INSERT INTO boxer
VALUES ('4', 'John','Johnowski','71');
INSERT INTO category_weight
VALUES ('1', '1','70','category1');
INSERT INTO category_weight
VALUES ('2', '71','100','category2');
INSERT INTO fight
VALUES ('1','1','1','1','2');
INSERT INTO fight
VALUES ('2','2','1','3','1');
Boxer with ID "1" won two fights in category1, so the result should be:
Lname Category Wins
Johnny category1 2
Here, try this:
SELECT b.lname,
cw.max_weight AS WEIGHT_CLASS,
COUNT(CASE WHEN f.winner = b.id THEN 1 ELSE NULL END) AS WINS
FROM boxer b
INNER JOIN fight f ON b.id = f.id_boxer1 OR b.id = f.id_boxer2
INNER JOIN category_weight cw ON f.id_category_weight = cw.id
GROUP BY b.lname, cw.max_weight

Check primary keys values

These are tables in SQLite: especie_similar
CREATE TABLE especie_similar (
id_especie INTEGER NOT NULL,
id_similar INTEGER NOT NULL,
PRIMARY KEY (
id_especie,
id_similar
),
FOREIGN KEY (
id_especie
)
REFERENCES especie (id_especie) ON DELETE CASCADE,
FOREIGN KEY (
id_similar
)
REFERENCES especie (id_especie) ON DELETE CASCADE
);
And especie table:
CREATE TABLE especie (
id_especie INTEGER PRIMARY KEY AUTOINCREMENT
NOT NULL,
nombre_especie VARCHAR NOT NULL,
cient_especie VARCHAR NOT NULL,
desc_especie TEXT,
nidificacion TEXT NOT NULL,
dimorfismo INTEGER NOT NULL,
genero_id INTEGER NOT NULL,
endemismo_id INTEGER NOT NULL,
abundancia_id INTEGER NOT NULL,
FOREIGN KEY (
genero_id
)
REFERENCES genero (id_genero),
FOREIGN KEY (
endemismo_id
)
REFERENCES endemismo (id_endemismo),
FOREIGN KEY (
abundancia_id
)
REFERENCES abundancia (id_abundancia)
);
My situation: Table especie has multiple datas and I want to insert in especie_similar ids from table especie.
How can i code a trigger or sql statement checking if id_especie and id_similar are not equals?
How can i code to retrieve all especies distinct of target id
(ex: table especie_similar has id_especie=1 and id_similar=2
indicating that species id 1 is similar to another species id 2 but
cannot insert id_especie=2 and id_similar=1 due to previous
duplicate data)?
Thanks and sorry my english is not good.
For question #1 you can use a standard SQL constraint:
create table especie_similar (
...
check (id_especie <> id_similar) -- your condition here
);
For question #2 you can use a standard "Recursive CTE". See SQLite WITH Clause. Example:
with recursive node as (
select id from especie_similar
where id_especie = 123 -- first node criteria here
union all
select s.id_especie
from node n
join especie_similar s on s.id_similar = n.id
)
select * from node;

Locking Order of table with foreign key constraint?

If I create a schema such as the following:
create table org
(
org_id bigint not null auto_increment,
name varchar(255) not null,
primary key(org_id)
);
create table user
(
user_id bigint not null auto_increment,
name varchar(255) not null,
org_id bigint not null,
primary key(user_id),
foreign key(org_id) references org (org_id)
);
Where the org table has one entry:
insert into org (name) values ('org 1');
If I run the following sql statement:
insert into user (name, org_id) values ('user 1', 1);
In what order will the tables be locked? Is it deterministic? What if there were a second foreign key constraint to another table?

SQLite cascading delete

The parent table is:
CREATE TABLE BHEAD (
ID INTEGER primary key asc,
DESCR TEXT,
LINECTR INT,
UNITCTR INT)
The child table is:
CREATE TABLE BDET (
ID INTEGER primary key asc,
BID INTEGER,
BCODE TEXT,
QTY INTEGER,
FOREIGN KEY (BID) REFERENCES BHEAD(ID) ON DELETE CASCADE
)
I also execute the SQL PRAGMA foreign_keys = ON;.
However, it does not work; when I delete one row from BHEAD, its associated rows in BDET are not gone...
Why was that?
What version of SQLite are you using?
Please see: Foreign Keys.
In order to use foreign key constraints in SQLite, the library must be compiled with neither SQLITE_OMIT_FOREIGN_KEY or SQLITE_OMIT_TRIGGER defined.
However, you can also implement on delete cascade to delete all child
rows when a parent row is deleted.
-- Create the test tables using ON DELETE CASCADE
DROP TABLE t3 PURGE;
--DROP TABLE t2 PURGE;
--DROP TABLE t1 PURGE;
CREATE TABLE t1 (
id NUMBER,
description VARCHAR2(50),
CONSTRAINT t1_pk PRIMARY KEY (id)
);
CREATE TABLE t2 (
id NUMBER,
t1_id NUMBER,
description VARCHAR2(50),
CONSTRAINT t2_pk PRIMARY KEY (id),
CONSTRAINT t2_t1_fk FOREIGN KEY (t1_id) REFERENCES t1 (id) ON DELETE CASCADE
);
CREATE TABLE t3 (
id NUMBER,
t2_id NUMBER,
description VARCHAR2(50),
CONSTRAINT t3_pk PRIMARY KEY (id),
CONSTRAINT t3_t2_fk FOREIGN KEY (t2_id) REFERENCES t2 (id)
);
INSERT INTO t1 VALUES (1, 't1 ONE');
INSERT INTO t2 VALUES (1, 1, 't2 ONE');
INSERT INTO t2 VALUES (2, NULL, 't2 TWO');
INSERT INTO t3 VALUES (1, 1, 't3 ONE');
INSERT INTO t3 VALUES (2, NULL, 't3 TWO');
COMMIT;
SELECT (SELECT COUNT(*) FROM t1) AS t1_count,
(SELECT COUNT(*) FROM t2) AS t2_count,
(SELECT COUNT(*) FROM t3) AS t3_count
FROM dual;
DELETE FROM t3;
rollback;
truncate table t1 ;
rollback;
truncate table t1 CASCADE;

What query creates a trigger to generate composite primary key with two fk?

I'm trying to write a command to create a trigger that generates the composite primary key. This pk is in turn based on two fk.
I'll write example tables to be more specific.
(Table I'm working on)
CREATE TABLE DB.MESSAGE (
TEXT CLOB NOT NULL,
SUBJECT VARCHAR2(2000) NOT NULL,
MSG_TYPE NUMBER(1) NOT NULL,
MAIL_ID NUMBER(10) NOT NULL
)
;
ALTER TABLE DB.MESSAGE ADD CONSTRAINT MSG_PK PRIMARY KEY ( MSG_TYPE, MAIL_ID ) ;
ALTER TABLE DB.MESSAGE ADD
(
CONSTRAINT MESSAGE_TYPE_ID_FK
FOREIGN KEY ( MSG_TYPE )
REFERENCES DB.TYPES ( TYPE_ID )
);
ALTER TABLE DB.MESSAGE ADD
(
CONSTRAINT MESSAGE_MAIL_FK
FOREIGN KEY ( MAIL_ID )
REFERENCES DB.EML_MAIL ( MAILTO_ID )
);
(Referenced tables)
CREATE TABLE DB.TYPES (
TYPE_ID NUMBER(13) NOT NULL,
NAME VARCHAR2(10) NOT NULL
)
;
CREATE TABLE DB.MAIL (
MAIL_ID NUMBER(10) NOT NULL,
MAIL VARCHAR2(350) NOT NULL
)
;
My query so far
create or replace
TRIGGER DB.TRG_MESSAGE_ID
BEFORE INSERT ON DB.MESSAGE
FOR EACH ROW
BEGIN
IF INSERTING THEN
IF :NEW."MSG_ID" IS NULL THEN
SELECT DB.TYPES.TYPE_ID ??????
INTO :NEW."MSG_ID" FROM dual;
END IF;
END IF;
END;
EDIT: So the thinking behind this question was that there would be a separated column with a concatenations of both keys that compose the composite key.
A friend told me this is wrong, you just put both fields as pk and that's that. Is this true?