How can I move several columns from one table to a new one to-many table? - sqlite

I'd like to refactor my database by splitting a single table into two. I'd like to moving a few existing columns to a new table. For instance, suppose I want to move the home_address and work_address fields in the below Employee table to a new Address table.
How can I accomplish this using sqlite?
Before:
Employee Table
employee_id (Primary)
name
home_address
home_city
work_address
work_city
After:
Employee Table
employee_id (Primary)
name
home_address_id
work_address_id
Address Table
address_id (Primary)
address
city

I prefer migrations to be simple and straightforward, without extra logic, etc. At least when you run them only once or so.
So, first check what is max(employee_id), below assumes that it less than 10000 (and it is integer).
create table employee_new(employee_id,name,home_address_id,work_address_id);
insert into employee_new select employee_id,name,employee_id,employee_id+10000 from employee;
create table address(address_id,address,city);
insert into address select employee_id,home_address,home_city from employee;
insert into address select employee_id+10000,work_address,work_city from employee;
alter table employee rename to employee_old;
alter table employee_new rename to employee;

Related

How to select entries from one table where a certain field is not existing in the other table

How to select entries in peewee ORM from one table where a certain field is not in the other table?
E.g.
How to count the employees which is there in tblemployees and not in tblcards?
select count(*) from tblEmployees
where name not in
(select employname from tblCards);
Note: Both fields, "name" and "employname" are not the respective primary/foreign keys).
You should provide your model definitions. But did you try something like:
Employee.select().where(Employee.name.not_in(Card.select(Card.employname))).count()

Denormalization - maintaining redundancy by using triggers in Oracle

I have a task for my university project where I have denormalized a table and now I have to implement a trigger in order to maintain redundancy. After following the book accordingly I'm stuck on the last step and I can't get my mind around it.
I have two tables - Supplier and Catalogue
**Supplier**
SupplierCode (primary key)
SupplierName
**Catalogue**
SupplierCode (foreign key)
CatalogueCode (both SupplierCode and CatalogueCode form a primary key)
CatalogueName
DateCreated
SupplierName (redundant column for denorm purposes)
When a new row is inserted in the Catalogue table I want that SupplierName field in the same table gets populated based on the SupplierCode which was inserted.
What I have so far:
We need to create a package as well
create or replace PACKAGE "PACK" AS
SUPPCODE NUMBER:=0;
SUPPNAME VARCHAR2(50);
END;
I have created a BEFORE INSERT TRIGGER on Catalogue table
create or replace TRIGGER CatalogueBefore
BEFORE INSERT OR UPDATE ON CATALOGUE
FOR EACH ROW
BEGIN
PACK.SUPPCODE:=:NEW.SUPPLIERCODE;
END;
I've then added an AFTER INSERT TRIGGER on Catalogue table
create or replace TRIGGER "AddNewCatalogue"
AFTER INSERT ON CATALOGUE
FOR EACH ROW
DECLARE
V_SUPPNAME SUPPLIER.SUPPLIERNAME%TYPE;
BEGIN
SELECT SUPPLIERNAME INTO V_SUPPNAME
FROM SUPPLIER
WHERE SUPPLIERCODE= PACK.SUPPCODE;
PACK.SUPPNAME:=V_SUPPNAME;
END;
After all of this I have the Supplier name held in my package in PACK.SUPPNAME but my question is how do I now use this variable when inserting a new row in the Catalogue table? I'm stuck at this for some time now and I'm probably missing something obvious. :) Any help is appreciated. Thanks.
P.S Please ignore uppercase vs. lowercase letters - I've just translated the names from my native language. :)
Thanks
I have denormalized a table and now I have to implement a trigger in order to maintain redundancy
[...]
When a new row is inserted in the Catalogue table I want that SupplierName field in the same table gets populated based on the SupplierCode which was inserted.
If those are your only requirements, all you need is one trigger to alter the record with the data from the second table. Something like that, maybe:
CREATE OR REPLACE TRIGGER CatalogueBefore
BEFORE INSERT OR UPDATE ON Catalogue
FOR EACH ROW
BEGIN
SELECT S.SupplierCode INTO :NEW.SupplierCode
FROM Supplier S
WHERE S.SupplierName = :NEW.SupplierName;
END;
That way, on update or insert into the table Catalogue, the SupplierCode will be overwritten by the code coming from Supplier table. See http://sqlfiddle.com/#!4/d79e0/1 for a live example.
Some notes though:
For this to work, Supplier.SupplierName should be an unique index too. In fact, the all thing is based on the assumption this is a natural key.
You very probably need an other trigger to deal with updates in the Supplier table. Say, when one supplier's name will change, the new name will have to be propagated to Catalogue.

Same attributes, different tables in one database in SQLite

I am just new in SQLite and I have this assignment in creating database schema using the said program.
I just want to ask if it is allowed to give a same attributes present in different tables inside a single database. Let me give the SQLite statements of two tables in one database.
BEGIN TRANSACTION;
/* Create a table called Employee */
CREATE TABLE Employee(Name text, Phone_number varchar);
/* Create a table called Company */
CREATE TABLE Company(Name text, Country text);
I am referring to attribute Name which appears twice in two tables. Will it affect or distorts some of the SQL queries execution in the database?
If you had tried it (in the command-line shell or on SQLFiddle), you would have found out that it is allowed.
However, it can affect your queries.
When you join these two tables, you have to explicitly specifiy which table's column you want:
CREATE TABLE Employee(ID, CompanyID, Name, Phone_number);
CREATE TABLE Company(ID, Name, Country);
SELECT Company.Name,
Employee.Name,
Phone_number
FROM Company
JOIN Employee ON Company.ID = Employee.CompanyID;
On the other hand, if you have a foreign key relationship, using the same name in both tables allows you to simplify the join condition:
CREATE TABLE Employee(EmployeeID, CompanyID, Name, Phone_number);
CREATE TABLE Company(CompanyID, Name, Country);
SELECT Company.Name,
Employee.Name,
Phone_number
FROM Company
JOIN Employee USING (CompanyID);

SQLite regular table and table for fts

I have table news (id, news_id, news_title) and I creat FTS table:
CREATE VIRTUAL TABLE news_search USING fts4 (news_title, tokenize=porter);
I use trigger to keep table NEWS and news_search in sync:
CREATE TRIGGER IF NOT EXISTS insert_news_trigger
AFTER INSERT ON news
BEGIN
INSERT OR IGNORE INTO news_search (news_title) VALUES (NEW.news_title);
END;
Question: how to use search? When I do MATCH in news_search table it returns me only records from this table, but I need *news_id* from news table. May be I should add *news_id* column to news_search table?
What is the proper way to use fts in sqlite?
Read the documentation; FTS tables also have a rowid column (also called docid) that you can set explicitly to the same value as the corresponding key of the original table.
Assuming that news.id is the rowid (i.e., INTEGER PRIMARY KEY), you should change your trigger to also copy that ID value into the news_search table.
You can the use that to look up the original record:
SELECT *
FROM news
WHERE id IN (SELECT docid
FROM news_search
WHERE news_title MATCH '😸')

create table with constraints from another table in sqlite?

I want create table from another table with constraint?
I used this query "create table destination as select * from source;" fro table creation.
But its copy only the column name in table without column constraint.
There is a special table named sqlite_master, holding the full CREATE TABLE statement for each table (it's modified as appropriate during ALTER TABLE).
I would make my application retrieve that CREATE TABLE statement:
SELECT sql FROM sqlite_master WHERE type='table' AND name='source';
Then I would replace the table name right after CREATE TABLE tokens, and execute the result as a new sqlite query.
I don't think that it's possible to do in sqlite's pure SQL without extensions.

Resources