How to add default value in SQLite? - sql

I had a table modified to add status column to it in this fashion
ALTER TABLE ITEM ADD COLUMN STATUS VARCHAR DEFAULT 'N';
However SQLite doesnt seem to add N to the column for any new ITEM created. Is the syntax wrong or is there any issue with SQLite and its support for defaults.
I am using SQLite 3.6.22

Looks good to me. Here are the Docs.
sqlite> create table t1 (id INTEGER PRIMARY KEY, name TEXT, created DATE);
sqlite> .table
t1
sqlite> .dump
PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE t1 (id INTEGER PRIMARY KEY, name TEXT, created DATE);
COMMIT;
sqlite> alter table t1 add column status varchar default 'N';
sqlite> .dump
PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE t1 (id INTEGER PRIMARY KEY, name TEXT, created DATE, status varchar default 'N');
COMMIT;
sqlite> insert into t1 (name) values ("test");
sqlite> select * from t1;
1|test||N
Dump your schema and verify that your table structure is there after calling ALTER TABLE but before the INSERT. If it's in a transaction, make sure to COMMIT the transaction before the insert.
$ sqlite3 test.db ".dump"

Related

postgres updatable view and unique constraints

in my simple application I would like to create a view in order to allow users filling data of my db.
Here a little example of my data
CREATE TABLE specie
(
specie_id INT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
nome_comune TEXT UNIQUE,
nome_scientifico TEXT UNIQUE
);
CREATE TABLE rilevatore
(
rilevatore_id INT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
nome_cognome TEXT UNIQUE,
telefono INTEGER,
email TEXT,
ente_appartenenza TEXT
);
CREATE TABLE evento_investimento
(
evento_id INT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
data DATE,
ora TIME WITHOUT TIME ZONE,
rilevatore_id INT REFERENCES rilevatore (rilevatore_id),
specie_id INT REFERENCES specie(specie_id),
);
This is the VIEW I created
CREATE VIEW investimenti_vista AS
SELECT
evento_investimento.evento_id,
evento_investimento.ora,
evento_investimento.data,
rilevatore.nome_cognome,
rilevatore.telefono,
rilevatore.email,
rilevatore.ente_appartenenza,
specie.nome_comune,
specie.nome_scientifico
from
evento_investimento
JOIN specie ON evento_investimento.specie_id = specie.specie_id
JOIN rilevatore ON evento_investimento.rilevatore_id = rilevatore.rilevatore_id;
When I attempt to fill the data I receive an error from postgres since view generated from different tables aren't updatable by default.
Thus, I implemetend the following trigger to overcome this issue.
CREATE OR REPLACE FUNCTION inserimento_vista() RETURNS trigger AS $$
BEGIN
INSERT INTO evento_investimento (data,ora)
VALUES (NEW.data,NEW.ora);
INSERT INTO rilevatore (nome_cognome, telefono, email, ente_appartenenza)
VALUES (NEW.nome_cognome, NEW.telefono, NEW.email, NEW.ente_appartenenza);
INSERT INTO specie (nome_comune, nome_scientifico)
VALUES (NEW.nome_comune, NEW.nome_scientifico);
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
create trigger inserimento_vista_trg
instead of insert on investimenti_vista for each row EXECUTE procedure inserimento_vista();
However this is not working due to unique contraints I have in the rilevatore and specie tables. How I can solve this?
Thanks
You might try to check for the existence of the conflicting values like this:
CREATE OR REPLACE FUNCTION inserimento_vista() RETURNS trigger AS $$
BEGIN
INSERT INTO evento_investimento (data,ora)
VALUES (NEW.data,NEW.ora);
if not exists(select * from rilevatore where rilevatore.nome_cognome=new.nome_cognome) then
INSERT INTO rilevatore (nome_cognome, telefono, email, ente_appartenenza)
VALUES (NEW.nome_cognome, NEW.telefono, NEW.email, NEW.ente_appartenenza);
end if;
if not exists(select * from specie where specie.nome_comune=new.nome_comune) then
INSERT INTO specie (nome_comune, nome_scientifico)
VALUES (NEW.nome_comune, NEW.nome_scientifico);
end if;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
You might want to add to this an update the specie and/or rilevatore tables with the non-conflicting values but that's up to you :-)

How to insert a newly generated id into another table with a trigger in postgresql?

Basically, users when they create a new record in mytable1, there is an id field that needs to be the same across multiple tables. I achieve this by having mytable2 with the s_id as primary key
My current function looks like
CREATE OR REPLACE FUNCTION test.new_record()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
BEGIN
case when new.s_id in (select s_id from mytable1) then
insert into mytable2 (sprn, date_created) select max(s_id) +1, now() from mytable2 ;
update mytable1 set new.s_id = (select max(b.s_id) from mytable2 b);
end case;
RETURN new;
END;
$function$;
Intended was when the s_id is replicated then it would create a new entry on mytable2. This new entry would then be updated onto mytable1
Problem with this function is that right now it does not recognise the new on the update part of the function.
How to keep the s_id take the value on every new insert ?
If you want to have one "generator" across multiple tables, create one sequence that is used across all those tables for the default value:
create sequence the_id_sequence;
create table one
(
id integer primary key default nextval('the_id_sequence')
.... other columns
);
create table two
(
id integer primary key default nextval('the_id_sequence')
.... other columns ...
);
If you want to replicate an ID from one table to another during insert, you only need one sequence:
create table one
(
-- using identity is the preferred over "serial" to auto-generate PK values
id integer primary key generated always as identity
);
create table two
(
id integer primary key
);
create or replace function insert_two()
returns trigger
as
$$
begin
insert into two (id) values (new.id);
return new;
end;
$$
language plpgsql;
create trigger replicate_id
before insert on one
for each row
execute procedure insert_two();
Then if you run:
insert into one (id) values (default);
A row with exactly the same id value will be inserted into table two.
If you don't have a generated ID column so far, use the following syntax:
alter table one
add testidcolumn bigint generated always as identity;

Oracle SQL to change column type from number to varchar2 while it contains data

I have a table (that contains data) in Oracle 11g and I need to use Oracle SQLPlus to do the following:
Target: change the type of column TEST1 in table UDA1 from number to varchar2.
Proposed method:
backup table
set column to null
change data type
restore values
The following didn't work.
create table temp_uda1 AS (select * from UDA1);
update UDA1 set TEST1 = null;
commit;
alter table UDA1 modify TEST1 varchar2(3);
insert into UDA1(TEST1)
select cast(TEST1 as varchar2(3)) from temp_uda1;
commit;
There is something to do with indexes (to preserve the order), right?
create table temp_uda1 (test1 integer);
insert into temp_uda1 values (1);
alter table temp_uda1 add (test1_new varchar2(3));
update temp_uda1
set test1_new = to_char(test1);
alter table temp_uda1 drop column test1 cascade constraints;
alter table temp_uda1 rename column test1_new to test1;
If there was an index on the column you need to re-create it.
Note that the update will fail if you have numbers in the old column that are greater than 999. If you do, you need to adjust the maximum value for the varchar column
Add new column as varchar2, copy data to this column, delete old column, rename new column as actual column name:
ALTER TABLE UDA1
ADD (TEST1_temp VARCHAR2(16));
update UDA1 set TEST1_temp = TEST1;
ALTER TABLE UDA1 DROP COLUMN TEST1;
ALTER TABLE UDA1
RENAME COLUMN TEST1_temp TO TEST1;
Look at Oracle's package DBMS_REDEFINE. With some luck you can do it online without downtime - if needed. Otherwise you can:
Add new VARCHAR2 column
Use update to copy NUMBER into VARCHAR2
Drop NUMBER column
Rename VARCHAR2 column
Here you go, this solution did not impact the existing NOT NULL or Primary key constraints. Here i am going to change the type of Primary key from Number to VARCHAR2(3), Here are the Steps on example table employee.
Take backup of table and Index, Constraints
created table employee_bkp
create table employee_bkp as select * from employee
commit;
Truncate the table to empty it
truncate table employee
Alter the table to change the type
ALTER TABLE employee MODIFY employee_id varchar2(30);
Copy the data back from backup table
insert into employee (select * from employee_bkp)
commit;
Verify

How to use default column value for the rowtype variable in PostgreSQL?

I have a table and a procedure like this:
CREATE TABLE test_table (
id SERIAL PRIMARY KEY,
info TEXT);
create or replace function test() returns void as
$$
declare
v_row test_table%ROWTYPE;
begin
v_row.info := 'test';
insert into test_table values (v_row.*);
end;
$$ language plpgsql;
select test();
ERROR: null value in column "id" violates not-null constraint
How to use default value for the v_row.id field? I know I could write
insert into test_table (info) values (v_row.info);
But in my real case I have a lot of such tables with many columns and I really want to avoid enumerating all the columns in the insert statement.
By writing insert into test_table values (v_row.*); you actually force postgres to insert NULL value into the id column.
You will need to run such code - either in application
v_row.id := nextval( 'mysequence' );
.. or in trigger
IF NEW.id IS NULL THEN
NEW.id := nextval( 'mysequence' );
END IF;
You can check, if Postgresql have a SEQUENCE for this column and then, if this column have a DEFAULT value set. In psql try:
\d+ test_table
You have to see somethink like this:
id | integer | default nextval('test_table_id_seq'::regclass) |
If there is not a default nextval('somethink'), then you have to check, if there is sequnence for this column:
\ds+
You have to see somethink like this:
public | test_table_id_seq | sequence
If you will not have a sequence, you have a CREATE it:
CREATE SEQUENCE test_table_id_seq;
And if you will have not a `default nextval('somethink'), you have use a ALTER TABLE:
ALTER TABLE test_table ALTER COLUMN id SET DEFAULT nextval('test_table_id_seq');
You can find about it some informations here: http://www.postgresql.org/docs/8.1/static/datatype.html#DATATYPE-SERIAL
Perhaps you can understand it, although English is not my native language...

When we create a table how to tall SQLITE to set default value of datetime to `now`?

We have something like:
CREATE TABLE IF NOT EXISTS files
(encoded_url varchar(65) UNIQUE NOT NULL primary key, modified DATETIME NOT NULL);
We want each time a new record is created to fill its modified field with now time automatically. Can we tall SQLite that it has to do such thing when we create a table or we should always insert nowwhen we fill in a row?
You can use default CURRENT_TIMESTAMP in the column specification:
sqlite> create table t (a datetime default CURRENT_TIMESTAMP, b text);
sqlite> insert into t(b) values ('hello');
sqlite> select * from t;
2011-10-16 17:29:54|hello
sqlite> insert into t(b) values ('hello again');
sqlite> select * from t;
2011-10-16 17:29:54|hello
2011-10-16 17:30:04|hello again
There are other date/time options, documented in the column definition part of the create table syntax docs.
CREATE TABLE IF NOT EXISTS files
(encoded_url varchar(65) UNIQUE NOT NULL primary key, modified DEFAULT (datetime('now','localtime')) NOT NULL);