how can you add multiple rows in sqlcl? - sql-insert

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>

Related

Error with csv file while importing it into sqlite3

So I am trying to import a csv file into a table with sqlite3 and I get an error, this is the table schema and the command I use to import the file and the error it appears in order:
CREATE TABLE Artist(
Art_ID int not null primary key,
Art_Name varchar(30),
Followers int,
Art_Genres varchar(200),
NumAlbums int,
YearFirstAlbum int,
Gender char(1),
Group_Solo varchar(5)
);
sqlite>
sqlite> .import '| tail -n +2 /Users/adrianogiunta/Desktop/artistDF.csv' Artist
<pipe>:1: expected 8 columns but found 1 - filling the rest with NULL
<pipe>:2: expected 8 columns but found 1 - filling the rest with NULL
<pipe>:3: expected 8 columns but found 1 - filling the rest with NULL
<pipe>:4: expected 8 columns but found 1 - filling the rest with NULL
<pipe>:5: expected 8 columns but found 1 - filling the rest with NULL
<pipe>:6: expected 8 columns but found 1 - filling the rest with NULL
and this for the rest of the 1035 rows.
These are the first lines of the csv file:
X,Artist,Followers,Genres,NumAlbums,YearFirstAlbum,Gender,Group.Solo
0,Ed Sheeran,52698756,"pop,uk pop",8,2011,M,Solo
1,Justin Bieber,30711450,"canadian pop,dance pop,pop,post-teen pop",10,2009,M,Solo
2,Jonas Brothers,3069527,"boy band,dance pop,pop,post-teen pop",10,2006,M,Group
3,Drake,41420478,"canadian hip hop,canadian pop,hip hop,pop rap,rap,toronto rap",11,2010,M,Solo
4,Chris Brown,9676862,"dance pop,pop,pop rap,r&b,rap",6,2005,M,Solo
5,Taylor Swift,23709128,"dance pop,pop,post-teen pop",10,2006,F,Solo
This is what my table shows afterward:
sqlite> SELECT * FROM Artist LIMIT 5;
0,Ed Sheeran,52698756,"pop,uk pop",8,2011,M,Solo|||||||
1,Justin Bieber,30711450,"canadian pop,dance pop,pop,post-teen pop",10,2009,M,Solo|||||||
2,Jonas Brothers,3069527,"boy band,dance pop,pop,post-teen pop",10,2006,M,Group|||||||
3,Drake,41420478,"canadian hip hop,canadian pop,hip hop,pop rap,rap,toronto rap",11,2010,M,Solo|||||||
4,Chris Brown,9676862,"dance pop,pop,pop rap,r&b,rap",6,2005,M,Solo|||||||
sqlite>
Thanks in advance for the help!
The .import command by default looks for SQLite's dump format. You need to enter .mode csv before trying to import a CSV. As the documentation says.

Result is not displayed in proper order in sqlite3

I have tried to display results from a table in sqlite3 database. I've tried .mode to column and ".header on", but the way it is displaying is not good.
This is the output. Can anyone please let me know how to solve this issue?
<pre>
sqlite> .mode columns
sqlite> SELECT * FROM pets;
_id name breed gender weight ␞---------- ---------- ---------- ---------- ----------␞1 Tommy Pomeranian 1 4 ␞2 Garfield Tabby 1 14 ␞3 Binx Bombay 1 6 ␞4 Binx Bombay 1 6 ␞sqlite>
</pre>
With .mode ascii, columns and rows are separated with unusual control characters in the output.
In theory, .mode column switches this back, but before sqlite3 version 3.17, it restored only the column separator, and left the old row separator. You should update your command-line shell; or as a workaround, execute .separator \t \n.

How to use `NULL` in a `where` clause

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

SQLite - Group by multiple columns, count distinct of one

Say I have the following table:
Commit File Past_Author
1 a Alice
1 a Bob
1 a Bob
1 b Alice
I'm looking to count the number of distinct authors for each file, summed by commit. In this case, I'd want 3 authors for commit 1 (2 for file a + 1 for file b).
I guess something like: SELECT Commit, SUM(NUM_AUTHORS) FROM (SELECT Commit, File, COUNT(DISTINT Past_Author) as NA FROM COMMITS GROUP BY File) GROUP BY Commit
This should do the trick.
SELECT Commit, SUM(NUM_AUTHORS) FROM
(
SELECT
Commit,
File,
COUNT(DISTINCT Past_Author) AS NUM_AUTHORS
FROM COMMITS
GROUP BY Commit, File
) AS AUTHOR_COUNT
GROUP BY Commit;

Common Table Expression in sqlite using rowid

I found a good article on converting adjacency to nested sets at http://dataeducation.com/the-hidden-costs-of-insert-exec/
The SQL language used is Microsoft SQL Server (I think) and I am trying to convert the examples given in the article to sqlite (as this is what I have easy access to on my Macbook).
The problem I appear to be having is converting the part of the overall CTE query to do with the Employee Rows
EmployeeRows AS
(
SELECT
EmployeeLevels.*,
ROW_NUMBER() OVER (ORDER BY thePath) AS Row
FROM EmployeeLevels
)
I converted this to
EmployeeRows AS
(
SELECT
EmployeeLevels.*,
rowid AS Row
FROM EmployeeLevels
ORDER BY thePath
)
and the CTE query runs (no syntax errors) but the output I get is a table without the Row and Lft and Rgt columns populated
ProductName ProductID ParentProductID TreePath HLevel Row Lft Rgt
----------- ---------- --------------- ---------- ---------- ---------- ---------- ----------
Baby Goods 0 0 1
Baby Food 10 0 0.10 2
All Ages Ba 100 10 0.10.100 3
Strawberry 200 100 0.10.100.2 4
Baby Cereal 250 100 0.10.100.2 4
Beginners 150 10 0.10.150 3
Formula Mil 300 150 0.10.150.3 4
Heinz Formu 310 300 0.10.150.3 5
Nappies 20 0 0.20 2
Small Pack 400 20 0.20.400 3
Bulk Pack N 450 20 0.20.450 3
I think the start of the problem is the Row is not getting populated and therefore the Lft and Rgt columns do not get populated by the following parts of the query.
Are there any sqlite experts out there to tell me:
am I translating the rowid part of the query correctly
does sqlite support a rowid in a part of a CTE query
is there a better way? :)
Any help appreciated :)
am I translating the rowid part of the query correctly
No.
The SQL:
SELECT
EmployeeLevels.*,
rowid AS Row
FROM EmployeeLevels
ORDER BY thePath
has the Row defined as the rowid of table EmployeeLevels in SQLite, ignoring the order clause. Which is different from the intention of ROW_NUMBER() OVER (ORDER BY thePath) AS Row
does sqlite support a rowid in a part of a CTE query
Unfortunately no. I assume you mean this:
WITH foo AS (
SELECT * FROM bar ORDER BY col_a
)
SELECT rowid, *
FROM foo
but SQLite will report no such column of rowid in foo.
is there a better way?
Not sure it is better but at least it works. In SQLite, you have a mechanism of temp table which exists as long as your connection opens and you didn't delete it deliberately. Rewrite the above SQL in my example:
CREATE TEMP TABLE foo AS
SELECT * FROM bar ORDER BY col_a
;
SELECT rowid, *
FROM foo
;
DROP TABLE foo
;
This one will run without SQLite complaining.
update:
As of SQLite version 3.25.0, window function is supported. Hence you can use row_number() over (order by x) expression in your CTE if you happen to use a newer SQLite

Resources