How to link SQL database entries? - sql

I have a SQLite database of notes that have columns _id, title, details, listid
_id is the auto incremented primary key
title and details are string data fields
listid is a foreign key pointing to a list name in another table.
I'd like to find a way to have notes that are in multiple lists or notes that are linked in such a way that updating one will update the other or be edited simultaneously by some other means.
The overall goal is to have copies of the same note in multiple lists where you edit one and the rest update automatically.
I've thought of adding an extra column with a sort of link id that will be shared by all linked notes, creating a way to update other notes.

Have three tables:
NOTE: _id, title, details
LIST: _id, listname
NOTES_IN_LIST: note_id, list_id
Then whenever you add a note to a list, you add a new row to NOTES_IN_LIST that connects that note ('s note_id) to the list ('s list_id).
Whenever you edit a note, you just edit it in the NOTE table.
Whenever you list the contents of the list that you have the id for, you do a SELECT something like:
SELECT title, details
from NOTE
where NOTE._id in (
SELECT note_id from NOTES_IN_LIST
where list_id=<your list id>
)
or
SELECT title, details
from NOTE, NOTES_IN_LIST
where
NOTE._id=NOTES_IN_LIST.note_id
and
NOTES_IN_LIST.list_id=<your list id>
Hmm, to transfer old notes to new structure, I would:
create a new notes table with a new autoincrement id field
then select distinct (note title, note details) into that new notes table
then join the old notes table to the new notes table on old_title=new_title and old_detail=new_detail, then select from that the new note id and the old list id, then insert the resulting table into the NOTES_IN_LIST table
then I think you can delete the old notes table
Make sure noone edits or adds notes while this is happening, or you will lose notes.
Also you will need to update the UI to work into the new notes table, put notes to lists not by copying but by inserting a new row into NOTES_IN_LIST, etc.

One note can have many lists, One list can have many notes.
you need an associative table that has a note id and a list id

SQLite 3.6.19+ natively supports (and enforces) Foreign Keys, see SQLite Foreign Key Support.

Related

Junction tables - how to find out ID to add?

I'm trying to code an application in Microsoft Blazor with a SQL Server Database.
In this part of the application I want the user to select pictures and add them to a collection that he creates with a new name.
There are three tables, for now each with two columns:
PictureID - PictureName
CollectionID - CollectionName
PictureID - CollectionID
PictureID and CollectionID in the first two tables are auto increment.
When the user adds a new collection with a new name and some selected pictures, I have the following information: PictureID, CollectionName.
My Problem: how do I get the ID of the newly added Collection, so I can add it to the junction table?
Do I really have to start a new query in the CollectionTable? And what should I search with the query - the highest ID? Not sure, if the newest is always the highest, if there were some deletions in the table. Seems to me, that I'm doing something wrong.
One method is to use the names to look up the ids:
insert into junction (collectionid, pictureid)
select c.collectionid, p.pictureid
from collections c cross join
pictures p
where c.collectionname = #cname and p.picturename = #pname;

Delete an item (row) from table but keep the unused ID number for a future insertion

I have a database with an "inventory" table which contains products from a shop. Each product is identified using an ID number set in the "ID" column of the table.
I want to be able to delete a product from the table, but keeping the deleted product's id number for future product insertions into the database.
As a demonstration I inserted 4 items and named all of them "test"
And just as an example I named the "deleted" product as "vacio" (empty in spanish) to show the one that i deleted.
Now, if want to add another product in the future, the id number 2 is unused and I want to add the product with that id number instead of 4 (following the given example).
The DELETE query is no good since it erases the id number as well so its a no go.
I thought about checking for the first row of the table that contains the value "vacio" and using the UPDATE query in all fields except id but this doesnt feel "classy" and is not very efficient as It should have to update values a lot of times.
Is there some nice way of doing this?
I would not actually recommend reusing old identifiers. For one, this prevents you from using the auto_increment feature, which mean that you need to manually handle the column for each and every insertion: this adds complexity and is not efficient. Also, it might cause integrity issues in your database if you have other tables referencing the product id.
But if you really want to go that way: I would go for the deletion option. If there are foreign keys referencing the column, make sure that they have the on delete cascade option enabled so data is properly purged from dependent tables when a product is dropped.
Then, you can fill the first available gap the next time your create a new product with the following query:
insert into products(id, categoria, producto)
select min(id) + 1, 'my new category', 'my new product'
from products p
where not exists (select 1 from products p1 where p1.id = p.id + 1)
You could have a new column ESTADO where you handle if a record is active (1) or inactive (0). Then, to obtain only "undeleted" records you just have to filter by the new column. That way, you also prevent changing the product name to "vacio", which might be useful in the future.

Sql server, insert data into two tables, populate one before the other

My first post here as I am starting in a new job where my old sql skills already are on the test - I am not advanced user from before either.
I believe there might be some answers here already that might be answering my question, but I am still a bit unfamiliar - both with the forum and more advanced sql syntaxes. Some answers are pretty old as well.
And - please excuse me for any grammatical errors.
Anyways, if anyone might be able to help.
I will be receive huge lists (.csv or similar) with data input.
The datalists will contain fields for type customerdata (name, address etc) and fields for type real estate/property data (street address, buildingIDs etc).
The customerdata and propertydata needs to be put into two separate tables.
My problem is like this:
- The two tables are depended on eachother as in the propertydata table needs to be populated with data first, which will generate a unique GUID - which again will be used when populating the customerdata table - connecting the customer to the correct property/real estate.
The first thing that came to mind is to populate all data into a temporary table.
But I am not quite sure how to loop through each row so I ensure that propertytable is populated first, then the customertable using the GUID.
Get data that involves propertydata and populate the property table
Get the unique GUID generated in property table
Get data that involves customerdata and populate the customer table - with correct GUID
Loop through rest of the set until there are no more rows with data.
I have seen some things like transactions, cursors, output etc that seems to be within my scope, but not sure which would be best way to solve my challenge? Am I near something when thinking like that?
EDIT:
These are example fields that will come as one row in .xlsx/.csv format.
Number of rows in such list will vary from time to time.
Property ID
Property address
Property building ID (only one)
Property established date
...Misc other property related fields
Customer ID
Customer Name
Customer Address
Postal code
...Misc other customer related fields
Fields 1 through 5 will need to populate a property table first. When each row in property table is populated it will generate unique GUID.
Then fields 6 through 10 will be used to populate a customer table, but also need to be populated with the corresponding unique GUID created above in the property table.
Property table:
Property ID
Property address
Property building ID (only one)
Property established date
...Misc other property related fields
UNIQUE PROPERTY GUID (created when populating each new row in table)
Customer table:
UNIQUE PROPERTY GUID
Customer ID
Customer Name
Customer Address
Postal code
...Misc other customer related fields
I suggest you use a staging table.
Load all data into a staging / temporary table and assign GUID numbers to each row.
Copy property details from staging table to property table taking GUID from the staging table
Copy customer details from staging table to customer table taking GUID from the staging table.
Delete data in staging table.
A quick example:
INSERT INTO PropertyDetails( GUID, PropertyID, PropertyAddress, ... )
SELECT GUID, PropertyID, PropertyAddress, ...
FROM StagingTable
INSERT INTO CustomertDetails( GUID, CustomerID, CustomerName, ... )
SELECT GUID, PropertyID, PropertyAddress, ...
FROM StagingTable

How to use SQL Server views with distinct clause to Link to a detail table?

I may be total standard here, but I have a table with duplicate values across the records i.e. People and HairColour. What I need to do is create another table which contains all the distinct HairColour values in the Group of Person records.
i.e.
Name HairColour
--------------------
Sam Ginger
Julie Brown
Peter Brown
Caroline Blond
Andrew Blond
My Person feature view needs to list out the distinct HairColours:
HairColour Ginger
HairColour Brown
HairColour Blond
Against each of these Person feature rows I record the Recommended Products.
It is a bit weird from a Relational perspective, but there are reasons. I could build up the Person Feature"View as I add Person records using say an INSTEAD OF INSERT trigger on the View. But it gets messy. An alternative is just to have Person Feature as a View based on a SELECT DISTINCT of the Person table and then link Recommended Products to this. But I have no Primary Key on the Person Feature View since it is a SELECT DISTINCT View. I will not be updating this View. Also one would need to think about how to deal with the Person Recommendation records when a Person Feature record disappeared since since it is not based on a physical table.
Any thoughts on this please?
Edit
I have a table of People with duplicate values for HairColour across a number of records, e.g., more than one person has blond hair. I need to create a table or view that represents a distinct list of "HairColour" records as above. Against each of these "HairColour" records I need link another table called Product Recommendation. The main issue to start with is creating this distinct list of records. Should it be a table or could it be a View based on a SELECT DISTINCT query?
So Person >- HairColour (distinct Table or Distinct View) -< Product Recommendation.
If HairColour needs to be a table then I need to make sure it has the correct records in it every time a Person record is added. Obviously using a View would do this automatically, but I am unsure whether you can can hang another table off a View.
If I understand correctly, you need a table with a primary key that lists the distinct hair colors that are found in a different table.
CREATE TABLE Haircolour(
ID INT IDENTITY(1,1) NOT NULL,
Colour VARCHAR(50) NULL
CONSTRAINT [PK_Haircolour] PRIMARY KEY CLUSTERED (ID ASC))
Then insert your records. If this is querying a table called "Person" it will look like this:
INSERT INTO Haircolour (Colour) SELECT DISTINCT HairColour FROM Person
Does this do what you are looking for?
UPDATE:
Your most recent Edit shows that you are looking for a many-to-many relationship between the Person and ProductRecommendation tables, with the HairColour table functioning as a cross reference table.
As ErikE points out, this is a good opportunity to normalize your data.
Create the HairColour table as described above.
Populate it from whatever source you like, for example the insert statement above.
Modify both the Person and the ProductRecommendation tables to include a HairColourID field, which is an integer foreign key that points to the PK field of the HairColour table.
Update Person.HairColourID to point to the color mentioned in the Person.HairColour column.
Drop the Person.HairColour column.
This involves giving up the ability to put free form new color names into the Person table. Any new colors must now be added to the HairColour table; those are the only colors that are available.
The foreign key constraint enforces the list of available colors. This is a good thing. Referential integrity keeps your data clean and prevents a lot of unexpected errors.
You can now confidently build your ProductRecommendation table on a data structure that will carry some weight.
Are you simply looking for a View of distinct hair colors?
CREATE VIEW YourViewName AS
SELECT DISTINCT HairColour
FROM YourTableName
You can query this view like a table:
SELECT 'HairColour: ' + HairColour
FROM YourViewName
If you are trying to create a new (temp) table, the syntax would look like:
SELECT Name, HairColour
INTO #Temp
FROM YourTableName
GROUP BY Name, HairColour
Here the GROUP BY is doing the same work that a DISTINCT keyword would do in the select list. This will create a temp table with unique combinations of "Name" and "HairColour".
You need to clear up a few things in your post (or in your mind) first:
1) What are the objectives? Forget about tables and views and whatever. Phrase your objectives as an ordinary person would. For example, from what I could gather from your post:
"My objective is to have a list of recommended products based on each person's hair colour."
2) Once you have that, check what data you have. I assume you have a "Persons" table, with the columns "Name" and "HairColour". You check your data and ask yourself: "Do I need any more data to reach my objective?" Based on your post I say yes: you also need a "matching" between hair colours and product ids. This must be provided, or programmed by you. There is no automatic method of saying for example "brown means products X,Y,Z.
3) After you have all the needed data, you can ask: Can I perform a query that will return a close approximation of my objective?
See for example this fiddle:
http://sqlfiddle.com/#!2/fda0d6/1
I have also defined your "Select distinct" view, but I fail to see where it will be used. Your objectives (as defined in your post) do not make this clear. If you provide a thorough list in Recommended_Products_HairColour you do not need a distinct view. The JOIN operation takes care of your "missing colors" (namely "Green" in my example)
4) When you have the query, you can follow up with: Do I need it in a different format? Is this a job for the query or the application? etc. But that's a different question I think.

Linking or Mapping two tables together

Consider my data as inventory list separated by categories.
When I started I had one table that should have been split into two tables, else in the oldTable the columns in a given row would have been un-related. I have created two new tables in my database, one for categories and the other for data/items. Now I am trying to use the oldTable existing data to fill the newTable data/items table so I can learn SQL and not have to manually do it. The categories table I filled in manually because I could not see how to do it otherwise.
The old table has:
tableName (
id,
categoryA,
categoryB,
categoryC,
categoryD,
categoryE,
categoryF,
isPriorityA,
isPriorityB,
isPriorityC,
isPriorityD,
isPriorityE,
isPriorityE
)
The new tables have:
Categories (
cat_id,
name
)
dataItem (
item_id,
cat_id,
name,
priority,
description,
URL
)
How do I force the new dataItem table to require the cat_id match one of the values in the Categories.cat_id table column? Perhaps to give an error if a value is added outside of the range? I believe this may be mapping or linking tables, to thereby make them relationship tables.
How do I copy the tableName data to the dataItem table one column at a time in alphabetical order bringing the name,priority with it and allowing it to auto-increment the item_id value?
Sounds like you want to use a foreign key to limit dataItem.cat_id to values in Categories.cat_Id. Something like this:
ALTER TABLE dataItem ADD FOREIGN KEY (cat_id) REFERENCES Categories(cat_id);
Exact syntax may depend on which database you are using. For more info on foreign keys see: http://www.w3schools.com/sql/sql_foreignkey.asp