Get custom field in sqlite - sqlite

I have two tables
Signers:
CREATE TABLE signers (idSigner INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, name TEXT, idNumber TEXT, rol TEXT)
and signatures:
CREATE TABLE signatures (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, documentId text, page INTEGER, coords TEXT, date TEXT, content TEXT, image TEXT, idSigner TEXT)
I want a select, that returns all the signers, and a custom column, with a true value, if the idSigner exists in the signatures table, and a false if not.
I have tryied with INNER JOINS, but I haven't achieved anything.
Expected result
idSigner name signed
1234 name1 true
2345 name2 false
3456 name3 false
Thanks!

To check whether a row exists, use EXISTS:
SELECT idSigner,
name,
EXISTS (SELECT 1
FROM signatures
WHERE idSigner = signers.idSigner
) AS signed
FROM signers;

Related

How do I create a view in which 'name' is replaced with 'new_name' if 'old_name' exist in the conversion table?

I would like to create a view that looks like the original tree_prototype table.
In this view the name should be set to the new_name value from the tree_prototype_conversion table if there is a matching old_name. If there is no match, the original name should stay.
I think I could do this in a case if I join on the name and old_name fields but that doesn't seem like the right approach. I feel like I am missing the obvious, and a CASE isn't it.
These are the tables in question:
CREATE TABLE IF NOT EXISTS tree
(
tree_id INTEGER PRIMARY KEY AUTOINCREMENT,
tree_prototype_id INTEGER,
FOREIGN KEY (tree_prototype_id) REFERENCES tree_prototype (tree_prototype_id)
);
CREATE TABLE IF NOT EXISTS tree_prototype
(
tree_prototype_id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT UNIQUE NOT NULL COLLATE NOCASE,
height REAL NOT NULL DEFAULT(10) CHECK (height > 0)
);
CREATE TABLE IF NOT EXISTS tree_prototype_conversion
(
old_name TEXT UNIQUE NOT NULL COLLATE NOCASE,
new_name TEXT UNIQUE NOT NULL COLLATE NOCASE
);
CREATE UNIQUE INDEX IF NOT EXISTS idx_tree_prototype
ON tree_prototype (name);
What I would like is a view that is both of these in one:
CREATE VIEW IF NOT EXISTS tree_prototype_converted AS
SELECT tree_prototype_id,
name,
height
FROM tree_prototype
WHERE name NOT IN (SELECT old_name FROM tree_prototype_conversion);
CREATE VIEW IF NOT EXISTS tree_prototype_converted AS
SELECT tree_prototype_id,
new_name as name,
height
FROM tree_prototype_conversion
JOIN tree_prototype as conversion on old_name=name;
After writing the CASE variant, my IDE suggested this:
CREATE VIEW IF NOT EXISTS tree_prototype_converted AS
SELECT tree_prototype_id,
coalesce(new_name, name) as name,
height
FROM tree_prototype
LEFT OUTER JOIN tree_prototype_conversion as conversion on old_name = name;
That looks right. Is it?

How to create a required many-to-many relationship in SQLite?

Suppose I have a schema like this:
CREATE TABLE Artist (
ArtistID INTEGER NOT NULL,
ArtistName TEXT NOT NULL,
PRIMARY KEY (ArtistID)
);
CREATE TABLE Song (
SongID INTEGER NOT NULL,
SongTitle TEXT NOT NULL,
PRIMARY KEY (SongID)
);
CREATE TABLE SongArtist (
SongID INTEGER NOT NULL,
ArtistID INTEGER NOT NULL,
PRIMARY KEY (SongID, ArtistID),
FOREIGN KEY (SongID) REFERENCES Song(SongID),
FOREIGN KEY (ArtistID) REFERENCES Artist(ArtistID)
);
By defining a column as NOT NULL I can semantically say that having a value in it is required. How would I make a many-to-many relationship required, but only in one direction?
In this situation, what I mean is this: How can I say that a Song row must have at least one Artist row associated with it through the SongArtist join table? If I were to represent a song as the JSON object below, this would be equivalent to saying that the songArtistIds array must have a length of 1 or higher.
{
songId: 745194,
songTitle: "Title",
songArtistIds: [523214]
}
However, an Artist row need not be associated with any Song row necessarily. An artist can have 0 or more songs, but a song must have 1 or more artists. How can I enforce this in SQLite? Also, if the answer is that I cannot do this in SQLite, then what alternative do I have for an embedded application?

Behavior of SqlLite rowid in case of a INTEGER primary key

If I have a non-integer primary-key the rowid is an auto-increment starting at 1.
sqlite> create table t1 (name text, documentid integer, primary key (name));
sqlite> insert into t1 (name, documentid) values ('max', 123);
sqlite> insert into t1 (name, documentid) values ('duf', 321);
sqlite> select rowid,* from t1;
1|max|123
2|duf|321
But if I have a INTEGER primary-key it seems the rowid is equal to it.
sqlite> create table t2 (name text, xid integer, primary key (xid));
sqlite> insert into t2 (name, xid) values ('max', 123);
sqlite> insert into t2 (name, xid) values ('duf', 321);
sqlite> select rowid,* from t2;
123|max|123
321|duf|321
Thats unexpected for me. I would expect rowid to behave like in the 1st sample.
Is that normal behaviour? Can I make it work like expected?
I am using SqlLite3 3.27
The problem is not the value as long it is uniqua (must be by definition of primary). But in JDBC I can not address ResultSet.getInt ("rowid") anymore - need to use getInt ("xid") instead" to make it work. Thats abnormal to a table with a non-integer primar-key.
An INTEGER PRIMARY KEY column is just an alias for the rowid. It acts the same (Having a value automatically assigned if left out when inserting a row), and doesn't even take up any extra space in the database. You can reference the column via its name, rowid, or any of the other standard aliases for rowid like oid.
From the documentation:
With one exception noted below, if a rowid table has a primary key that consists of a single column and the declared type of that column is "INTEGER" in any mixture of upper and lower case, then the column becomes an alias for the rowid. Such a column is usually referred to as an "integer primary key". A PRIMARY KEY column only becomes an integer primary key if the declared type name is exactly "INTEGER". Other integer type names like "INT" or "BIGINT" or "SHORT INTEGER" or "UNSIGNED INTEGER" causes the primary key column to behave as an ordinary table column with integer affinity and a unique index, not as an alias for the rowid.
If you just do
INSERT INTO t2(name) VALUES ('max');
a value will be automatically generated for xid instead of explicitly using the one provided in the insert like in your example.
Yes it's the normal behavior.
When you define an integer column xid as primary key, then xid is just an alias of rowid.
What you can do is define xid as UNIQUE and not PRIMARY KEY:
create table t2 (name text, xid integer unique)
Then you will have the functionality that you want, because the rowid will be a different auto increment column.
Or define xid as TEXT:
create table t2 (name text, xid text, primary key (xid));
In this case also rowid is a different column and don't worry about the data you store in xid.
You can treat this column just like an integer column so you can perform any arithmetic calculation and aggregation.
You can find more here: https://www.sqlite.org/rowidtable.html

Is it possible to insert the specified value in autoincrement column?

I need to copy one table to another and both tables contain column with AUTOINCREMENT. Is it possible to insert a defined value into AUTOINCREMENT column.
Tables:
CREATE TABLE tmptimetables (
_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
_title NVARCHAR(256) NOT NULL,
_weeks INTEGER NOT NULL,
_first_week_date INTEGER NOT NULL,
_auto_complete INTEGER NOT NULL,
_first_lesson_time INTEGER NOT NULL,
_lesson_duration INTEGER NOT NULL,
_break_duration INTEGER NOT NULL,
_color INTEGER NOT NULL,
_symbol NCHAR(1) NOT NULL
);
CREATE TABLE timetables (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
title NVARCHAR(256) NOT NULL,
weeks INTEGER NOT NULL,
first_week_date INTEGER NOT NULL,
auto_complete INTEGER NOT NULL,
first_lesson_time INTEGER NOT NULL,
lesson_duration INTEGER NOT NULL,
break_duration INTEGER NOT NULL,
color INTEGER NOT NULL,
symbol NCHAR(1) NOT NULL
);
My SQL request:
INSERT INTO timetables (
auto_complete,
break_duration,
color,
first_lesson_time,
first_week_date, id,
lesson_duration,
symbol,
title,
weeks
)
SELECT
_auto_complete,
_break_duration,
_color,
_first_lesson_time,
_first_week_date,
_id,
_lesson_duration,
_symbol,
_title,
_weeks
FROM tmptimetables
AUTOINCREMENT can only be used for a column that is INTEGER PRIMARY KEY, it is INTEGER PRIMARY KEY that is the factor that makes the column a special column whereby if the value is not provided when inserting a row that a unique integer will be assigned.
So be the column INTEGER PRIMARY KEY or INTEGER PRIMARY KEY AUTOINCREMENT you can specify an integer value and a row may be inserted with the given value.
A row will not be inserted with a given value if that value is not unique.
For example if the table timetables is currently :-
Then
INSERT INTO timetables (id,title,weeks,first_week_date,auto_complete,first_lesson_time,lesson_duration,break_duration,color,symbol) VALUES (null,'mytitle',78,86000,23,1800,900,200,16,'E');
Would insert a new row with the id as determined by SQLite's algorithm for providing a unique id (probably 5).
If the id were changed to be provided (i.e. not null) say to 10 as per :-
INSERT INTO timetables (id,title,weeks,first_week_date,auto_complete,first_lesson_time,lesson_duration,break_duration,color,symbol) VALUES (10,'mytitle',78,86000,23,1800,900,200,16,'E');
Then the id for the new row would be 10.
However if then using (the same SQL but with the last column value changed) :-
INSERT INTO timetables (id,title,weeks,first_week_date,auto_complete,first_lesson_time,lesson_duration,break_duration,color,symbol) VALUES (10,'mytitle',78,86000,23,1800,900,200,16,'Z');
A new row would not be inserted as a row with an id of 10 already exists.
Finally if the id is not given (null is used) but the SQL is otherwise the same a new row is inserted with a unique id being provided by SQLite e.g.
INSERT INTO timetables (id,title,weeks,first_week_date,auto_complete,first_lesson_time,lesson_duration,break_duration,color,symbol) VALUES (null,'mytitle',78,86000,23,1800,900,200,16,'Z');
So the end result of following the above is :-
AUTOINCREMENT
The AUTOINCREMENT keyword, only usable for an INTEGER PRIMARY COLUMN, invokes a different algorithm for determining the next sequence to ensure that the next sequence/id is always greater, whilst without AUTOINCREMENT a lower sequence/id can be applied.
The AUTOINCREMENT keyword does not specify that if a value for the column is not provided then a sequence/id is applied it is INTEGER PRIMARY KEY that specifies that. Well actually, by default, i.e. unless WITHOUT ROWID is specified, this happens for all tables. It's just the the special rowid column is hidden. Specifying <column_name> INTEGER PRIMARY KEY (where is a valid column name) creates an alias of the rowid.
For example using SELECT rowid,* FROM timetables produces :-
SQLite Autoincrement
Rowid Tables

How do I specify a Primary Key in Sqlite

How to define your specified attribute like StudentId in student table as Primary key in sqlite
CREATE TABLE Student(
id INTEGER PRIMARY KEY,
first_name TEXT,
last_name TEXT
);
From the Sqlite spec:
One exception to the typelessness of
SQLite is a column whose type is
INTEGER PRIMARY KEY. (And you must use
"INTEGER" not "INT". A column of type
INT PRIMARY KEY is typeless just like
any other.) INTEGER PRIMARY KEY
columns must contain a 32-bit signed
integer. Any attempt to insert
non-integer data will result in an
error.
http://www.sqlite.org/datatypes.html
You can also place a primary key on the arbitrary blobish data eg:
CREATE TABLE Student(id PRIMARY KEY, name)
Its a bit risky cause
INSERT INTO Student(1, "hello")
INSERT INTO Student("1", "hello")
will result in two rows.
If you need a unique constraint on other stuff you can try using the Create Index command
CREATE TABLE Students (
StudentId INTEGER PRIMARY KEY,
Name VARCHAR(80)
)
is one simple way.

Resources