SQLite - create table if not exists - sqlite

What is the create table statement in SQLite meant to return?
I have observed create table if not exists returning both a 0 and 1 when the table does in fact exist. Is the return value a reliable indication of whether the table does exist or not? I would expect the statement to return a 0 if the table already exists and a 1 when it does not, similar to an insert statement.

Changes returns the number of affected rows.
This values is meaningless for CREATE TABLE statements.
There is no easy way to determine whether the CREATE TABLE IF NOT EXISTS statement did the creation or not.
You should check beforehand with PRAGMA table_info.

The if not exists syntax makes the command succeed even if the table already exists. It just doesn't do anything.
I'm not sure what you're referring to with "returns 1" unless you're talking about the command-line client. In that case, if you just remove the if not exists from your create statement, the command will return 1 (indicating failure) if the table exists.

Related

ORA-00001: unique constraint (ABC.XY_PK) violated Error

before inserting in the table i am validating if the ID already exists in table.
It does not exists. Even though it through this error. Is there any possibility that the table does not allow to insert may be permission issue.
I have that insert query in a procedure, is there a possibility that due to procedure permission it doesn't allow.
If you check in the first statement/transaction for existences and you run this SP in parallel it is possible that the second (INSERT) statement/transaction fails.
In this case you can use a MERGE statement which either inserts the data or updates on existences in one transaction.

Conditionally add columns in SQLite

I've seen enough answers to know you can't easily check for columns in SQLITE before adding. I'm trying to make a lazy person's node in Node-Red where you pass a message to SQLITE which is the query. Adding a table if it does not exist is easy.
msg.topic='create table IF NOT EXISTS fred (id PRIMARY KEY);'; node.send(msg);
it occurred to me that adding a table which had the names of the fields would be easy - and if the field name is not in the table.... then add the field. BUT you can't add multiple fields at once - so I can't do this...
msg.topic='create table IF NOT EXISTS fred (id PRIMARY KEY, myfields TEXT);'; node.send(msg);
The problem with THAT is that I can't add this in later, there's no way to check before adding a field it the table exists!
This is what I WANT
msg.topic='create table IF NOT EXISTS fred (id PRIMARY KEY, myfields TEXT);'; node.send(msg);
msg.topic='if not (select address from myfields) alter table fred add column address text';
I just cannot think of any way to do this - any ideas anyone (the idea is that the node-red node would input a table, field and value and if the table didn't exist it would be created, if the field didn't exist it would be created, all before trying to add in the value).
You won't be able to make the ALTER TABLE conditional in the SQL itself. You'll need to handle that from your calling script.
Alternately, simply attempt to add the column to the table and accept failure as an outcome. Assuming the table exists, the only failure reason you could encounter is that the column already exists.
If you'd like to do something more graceful, you can check if the column exists in advance, then conditionally run the SQL from your calling application.

Check if record exists, if it does add 1 (inside procedure)

I am trying to check if an email address already exists, and add 1 if it does (and 1 if even the email+1 exists and so on). But so far I can't even figure out how to check if it exists, inside a procedure.
if exists (select 1 from table where email='something') then ...
Gives back an error ("function or pseudo-column 'EXISTS' may be used inside a SQL statement only)". Tried other stuff as well, but those might not be worth mentioning.
After I have this I plan on making a while loop for adding 1 as much as needed.
You can select the number of matching records into a variable (which you have declared), and then check that variable's value:
select count(*) into l_count
from my_table
where email = 'something';
if l_count > 0 then
-- record exists
...
else
-- record does not exist
...
end if;
select ... into always has to get exactly one record back, and using the count aggregate function means that happens, evenif more than one matching record exists.
That hopefully covers your specific issue about checking for existance. As for your underlying goal, it sounds like you're trying to find an unused value by incrementing a suffix. If so, this similar question might help. That is looking for usernames rather than emails,but the principle is the same.
As pointed out in comments, simultaneous calls to your procedure might still try to use the same suffix value; so you still need a unique constraint, and handling for that being violated in that scenario. I think that's beyond what you asked about here though.

Is this normal behavior for a unique index in Sqlite?

I'm working with SQLite in Flash.
I have this unique index:
CREATE UNIQUE INDEX songsIndex ON songs ( DiscID, Artist, Title )
I have a parametised recursive function set up to insert any new rows (single or multiple).
It works fine if I try to insert a row with the same DiscID, Artist and Title as an existing row - ie it ignores inserting the existing row, and tells me that 0 out of 1 records were updated - GOOD.
However, if, for example the DiscId is blank, but the artist and title are not, a new record is created when there is already one with a blank DiscId and the same artist and title - BAD.
I traced out the disc id prior to the insert, and Flash is telling me it's undefined. So I've coded it to set anything undefined to "" (an empty string) to make sure it's truly an empty string being inserted - but subsequent inserts still ignore the unique index and add a brand new row even though the same row exists.
What am I misunderstanding?
Thanks for your time and help.
SQLite allows NULLable fields to participate in UNIQUE indexes. If you have such an index, and if you add records such that two of the three columns have identical values and the other column is NULL in both records, SQLite will allow that, matching the behavior you're seeing.
Therefore the most likely explanation is that despite your effort to INSERT zero-length strings, you're actually still INSERTing NULLs.
Also, unless you've explicitly included OR IGNORE in your INSERT statements, the expected behavior of SQLite is to throw an error when you attempt to insert a duplicate INDEX value into a UNIQUE INDEX. Since you're not seeing that behavior, I'm guessing that Flash provides some kind of wrapper around SQLite that's hiding the true behavior from you (and could also be translating empty strings to NULL).
Larry's answer is great. To anyone having the same problem here's the SQLite docs citation explaining that in this case all NULLs are treated as different values:
For the purposes of unique indices, all NULL values are considered
different from all other NULL values and are thus unique. This is one
of the two possible interpretations of the SQL-92 standard (the
language in the standard is ambiguous). The interpretation used by
SQLite is the same and is the interpretation followed by PostgreSQL,
MySQL, Firebird, and Oracle. Informix and Microsoft SQL Server follow
the other interpretation of the standard, which is that all NULL
values are equal to one another.
See here: https://www.sqlite.org/lang_createindex.html

How to create ot replace table

Is there any way in teradata to
CREATE OR REPLACE VOLATILE TABLE
AS
(
SELECT
)
I need to make sure that it does not stop if the table already exists
As a Volatile Table is only visible within the current session you should know which tables have been created.
Otherwise i would simply try a DROP TABLE first and ignore a possible "object does not exist" error.
Short answer: No. Volatile table definitions are not stored in the data dictionary table DBC.Tables. Unlike a Global Temporary table the instantiation of a volatile table is also not tracked by a dictionary table in DBC.TempTables.
Longer answer: You can but it depends on where your SQL is executing.
You can check simply check for the existence of the table using something like SELECT 1 FROM {VolatileTableName} WHERE 1=0; or SELECT 'X' FROM {VolatileTableName] GROUP BY 1; and trap the error if the object doesn't exist. If you don't get an error the object exists. Without knowing where your code is running (BTEQ, Stored Procedure, Macro) it is difficult to explain the appropriate error handling.

Resources