In sqlite3 I am combining entries from various tables in a new table (making use ot primary and foreign key contsraints; for details see at the bottom):
select * from files;
id file description
---------- -------------- ----------------
1 testmodel1.dat first test model
2 testmodel2.dat second test mode
select * from patches;
id patch description
---------- ---------- ------------
1 testpatch test patch
Combined table:
select * from patched_files;
id files_id patches_id
---------- ---------- ----------
1 1 NULL
2 1 1
3 2 1
Some files do get patched some not (sometimes the same file).
I would like to retrieve this view from the database (expected result):
id file patch
---------- -------------- ----------
1 testmodel1.dat
2 testmodel1.dat testpatch
3 testmodel2.dat testpatch
I tried this:
select patched_files.id as id,patched_files.files_id as file_id, files.file as file, patched_files.patches_id as patch_id, patches.patch as patch
from patched_files, files, patches
where patched_files.files_id=files.id and patched_files.patches_id=patches.id;
id files_id file patches_id patch
---------- ---------- -------------- ---------- ----------
2 1 testmodel1.dat 1 testpatch
3 2 testmodel2.dat 1 testpatch
Here, I am missing the unpatched file (rowid 1) and I understand why.
So I added an or:
select patched_files.id as id,patched_files.files_id as file_id, files.file as file, patched_files.patches_id as patch_id, patches.patch as patch
from patched_files, files, patches
where patched_files.files_id=files.id and (patched_files.patches_id=patches.id or patched_files.patches_id is NULL);
id file_id file patch_id patch
---------- ---------- -------------- ---------- ----------
1 1 testmodel1.dat NULL testpatch
2 1 testmodel1.dat 1 testpatch
3 2 testmodel2.dat 1 testpatch
I understand why this is happening (composite table from "files" and "patches").
How can I avoid the patch name being stated if the patch_id is NULL?
Do I need to insert a "dummy" in the "patches" table?
Recreating the example:
-- original files:
create table files (id integer primary key, file text, description text);
insert into files (file, description) values('testmodel1.dat', 'first test model');
insert into files (file, description) values('testmodel2.dat', 'second test model');
-- patches:
create table patches (id integer primary key, patch text, description text);
insert into patches (patch, description) values('testpatch', 'test patch');
-- patched files (combination of files and patches):
create table patched_files (id integer primary key, files_id integer references files(id) on delete restrict deferrable initially deferred, patches_id integer references patches(id) on delete restrict deferrable initially deferred);
insert into patched_files (files_id) values(1);
insert into patched_files (files_id, patches_id) values(1,1);
insert into patched_files (files_id, patches_id) values(2,1);
You are looking for an outer join:
select f.id, f.file, p.patch, p.description
from files f
left join patched_files pf on pf.files_id = f.id
left join patches p on p.id = pf.patches_id
Online example: http://rextester.com/ZNMAY53081
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 am trying to add multiple rows in my table. i tried to follow some of the online solutions but i keep getting ORA-00933: SQL command not properly ended.
how do i add multiple rows at once.
insert into driver_detail values(1003,'sajuman','77f8s0990',1),
(1004,'babu ram coi','2g64s8877',8);
INSERT ALL is one way to go.
SQL> create table driver_detail (id integer, text1 varchar2(20), text2 varchar2(20), some_num integer);
Table DRIVER_DETAIL created.
SQL> insert all
2 into driver_detail (id, text1, text2, some_num) values (1003, 'sajuman', '77f8s0090', 1)
3 into driver_detail (id, text1, text2, some_num) values (1004, 'babu ram coi', '2g64s887', 8)
4* select * from dual;
2 rows inserted.
SQL> commit;
Commit complete.
SQL> select * from driver_detail;
ID TEXT1 TEXT2 SOME_NUM
_______ _______________ ____________ ___________
1003 sajuman 77f8s0090 1
1004 babu ram coi 2g64s887 8
But SQLcl is a modern CLI for the Oracle Database, surely there might be a better way?
Yes.
Put your rows into a CSV.
Use the LOAD command.
SQL> delete from driver_detail;
0 rows deleted.
SQL> help load
LOAD
-----
Loads a comma separated value (csv) file into a table.
The first row of the file must be a header row. The columns in the header row must match the columns defined on the table.
The columns must be delimited by a comma and may optionally be enclosed in double quotes.
Lines can be terminated with standard line terminators for windows, unix or mac.
File must be encoded UTF8.
The load is processed with 50 rows per batch.
If AUTOCOMMIT is set in SQLCL, a commit is done every 10 batches.
The load is terminated if more than 50 errors are found.
LOAD [schema.]table_name[#db_link] file_name
SQL> load hr.driver_detail /Users/thatjeffsmith/load_example.csv
--Number of rows processed: 4
--Number of rows in error: 0
0 - SUCCESS: Load processed without errors
SQL> select * from driver_detail;
ID TEXT1 TEXT2 SOME_NUM
_______ _________________ ______________ ___________
1003 'sajuman' '77f8s0990' 1
1004 'babu ram coi' '2g64s8877' 8
1 'hello' 'there' 2
2 'nice to' 'meet you' 3
SQL>
I'm working pulling RedHat vulnerability information and I am stuck at the sql query :) Essentially I have 2 tables (cve, errata) where data is kept and a third (references) that is a reference table with ids from tables errata and cve.
What I'm looking to extract is information from both tables, like this:
name_from_errata name_from_cve severity_from_errata releasedata_from_errata
RHSA-2017:0837 CVE-2017-5208 important 2017-03-23...
RHSA-2017:0837 CVE-2017-5332 moderate 2017-03-23...
RHSA-2017:0837 CVE-2017-5333 important ............
RHSA-2017:0837 CVE-2017-6009 important ............
.........................
Thanks!
Mario
For example this link lists 6 vulnerabilities
RedHat Advisory sample
CVE-2017-5208
CVE-2017-5332
CVE-2017-5333
CVE-2017-6009
CVE-2017-6010
CVE-2017-6011
Sqlite3 Database available # cvrf
[localhost cvrf]$ sqlite3 cvrf.db
sqlite> .headers on
sqlite> .mode column
sqlite> .tables
cve errata package relationship`
sqlite> .schema cve
CREATE TABLE "cve" ("id" INTEGER NOT NULL PRIMARY KEY, "name" VARCHAR(255) NOT NULL, "severity" VARCHAR(255), "cvss_score" VARCHAR(255), "publicdate" DATETIME);
CREATE UNIQUE INDEX "cve_name" ON "cve" ("name");`
sqlite> .schema errata
CREATE TABLE "errata" ("id" INTEGER NOT NULL PRIMARY KEY, "name" VARCHAR(255) NOT NULL, "severity" VARCHAR(255), "releasedate" DATETIME);
CREATE UNIQUE INDEX "errata_name" ON "errata" ("name");`
sqlite> .schema relationship
CREATE TABLE "relationship" ("id" INTEGER NOT NULL PRIMARY KEY, "errata_id" INTEGER NOT NULL, "cve_id" INTEGER NOT NULL, FOREIGN KEY ("errata_id") REFERENCES "errata" ("id"), FOREIGN KEY ("cve_id") REFERENCES "cve" ("id"));
CREATE INDEX "relationship_errata_id" ON "relationship" ("errata_id");
CREATE INDEX "relationship_cve_id" ON "relationship" ("cve_id");
CREATE UNIQUE INDEX "relationship_errata_id_cve_id" ON "relationship" ("errata_id", "cve_id");
Get a list of advisories for the last 2 days ( I need last day but today there was no advisory )
sqlite> SELECT * FROM errata WHERE releasedate > (SELECT DATETIME('now', '-2 day'));
id name severity releasedate
---------- -------------- ---------- --------------------
2722 RHSA-2017:0837 important 2017-03-23T00:21:00Z
2723 RHSA-2017:0838 moderate 2017-03-23T02:35:00Z
2724 RHSA-2017:0484 moderate 2017-03-23T04:59:00Z
2725 RHSA-2017:0494 moderate 2017-03-23T04:59:00Z
2726 RHSA-2017:0495 moderate 2017-03-23T05:04:00Z
2727 RHSA-2017:0486 moderate 2017-03-23T05:04:00Z
Get a list of ids associated with errata is '2722'
sqlite> select cve_id from relationship where errata_id='2722';
cve_id
----------
5002
5003
5004
5005
5006
5007
Get a list of cve names associated with errata name RHSA-2017:0837 ( errata id 5002 )
qlite> select * from cve where id='5002';
id name severity cvss_score publicdate
---------- ------------- ---------- ---------- --------------------
5002 CVE-2017-5208 important NULL 2017-01-08T00:00:00Z
sqlite> select * from cve where id='5003';
id name severity cvss_score publicdate
---------- ------------- ---------- ---------- --------------------
5003 CVE-2017-5332 moderate NULL 2017-01-10T00:00:00Z
sqlite> select * from cve where id='5004';
id name severity cvss_score publicdate
---------- ------------- ---------- ---------- --------------------
5004 CVE-2017-5333 important NULL 2017-01-10T00:00:00Z
sqlite> select * from cve where id='5005';
id name severity cvss_score publicdate
---------- ------------- ---------- ---------- --------------------
5005 CVE-2017-6009 important NULL 2017-02-16T00:00:00Z
sqlite> select * from cve where id='5006';
id name severity cvss_score publicdate
---------- ------------- ---------- ---------- --------------------
5006 CVE-2017-6010 moderate NULL 2017-02-16T00:00:00Z
sqlite> select * from cve where id='5007';
id name severity cvss_score publicdate
---------- ------------- ---------- ---------- --------------------
5007 CVE-2017-6011 moderate NULL 2017-02-16T00:00:00Z
Join the tables:
SELECT e.name, c.name, e.severity, e.releasedate
FROM errata e
JOIN relationship r ON e.id = r.errata_id
JOIN cve c ON c.id = r.cve_id
WHERE e.releasedate > DATETIME('now', '-2 day')
sqlite> create table foo(x TEXT PRIMARY KEY, y TEXT UNIQUE);
sqlite> select * from sqlite_master;
table|foo|foo|2|CREATE TABLE foo(x TEXT PRIMARY KEY, y TEXT UNIQUE)
index|sqlite_autoindex_foo_1|foo|3|
index|sqlite_autoindex_foo_2|foo|4|
For user-defined indices, the last column of sqlite_master tells me what columns they are on. But as you can see, for the indices implicitly created by (non-rowid) PRIMARY KEY and UNIQUE, this information is absent. Is there a reliable way for me to tell which autoindex is which?
There is no difference between internal and explicitly-created indexes; you can get information about them with the same PRAGMAs (index_list, index_info, index_xinfo):
sqlite> pragma index_list(foo);
seq name unique origin partial
---------- ---------------------- ---------- ---------- ----------
0 sqlite_autoindex_foo_2 1 u 0
1 sqlite_autoindex_foo_1 1 pk 0
sqlite> pragma index_xinfo(sqlite_autoindex_foo_1);
seqno cid name desc coll key
---------- ---------- ---------- ---------- ---------- ----------
0 0 x 0 BINARY 1
1 -1 0 BINARY 0
sqlite> pragma index_xinfo(sqlite_autoindex_foo_2);
seqno cid name desc coll key
---------- ---------- ---------- ---------- ---------- ----------
0 1 y 0 BINARY 1
1 -1 0 BINARY 0
I am using SQLite. There are two tables shown below.
Transaction_Tbl
ID Name Credit/Debit Value
1 ABC credit 10
1 ABC credit 10
2 DEF credit 20
2 DEF debit 40
(record for third employee EFG not present in the table)
Based on the table, Emp_Tbl must be updated as below...
Emp_Table
ID Name Avg(Credit-Debit)
1 ABC 20
2 DEF -20
3 EFG 0 (as no records for EFG in Transaction_Tbl)
Now if there is a record for EFG in Transaction_Tbl for Debit, then in Emp_Tbl, the record for EFG must be negative (credit - debit => where credit must be taken as zero as no records for credit.).
How to do it?
Assuming there's a table names listing all names (else where would efg sprint out from?!), then something like...:
sqlite> create table trans (id smallint, name string, cord string, value int);
sqlite> insert into trans(id,name,cord,value) values(1,'abc','credit',10);
sqlite> insert into trans(id,name,cord,value) values(1,'abc','credit',10);
sqlite> insert into trans(id,name,cord,value) values(2,'def','credit',20);
sqlite> insert into trans(id,name,cord,value) values(2,'def','debit',40);
sqlite> select * from trans;
1|abc|credit|10
1|abc|credit|10
2|def|credit|20
2|def|debit|40
sqlite> create table names (name string);
sqlite> insert into names(name) values('abc');
sqlite> insert into names(name) values('def');
sqlite> insert into names(name) values('efg');
to create and populate the tables and check the main one, then
sqlite> select names.name, sum(case trans.cord when 'credit' then trans.value when 'debit' then -trans.value else 0 end) from names left outer join trans on names.name=trans.name group by names.name;
abc|20
def|-20
efg|0
seems roughly what you're after, right?