1 to Many Sql insert - sql

I'm having problems figuring out how to insert a row into my database. I have an experiment table which has the following columns
CREATE TABLE [dbo].[Experiment] (
[ExperimentId] INT IDENTITY (1, 1) NOT NULL,
[Experiment] VARCHAR (100) NOT NULL,
[Account] VARCHAR (100) NOT NULL,
[Profile] VARCHAR (100) NOT NULL,
[Property] VARCHAR (100) NOT NULL,
[BucketId] INT NULL,
CONSTRAINT [PK_Experiment] PRIMARY KEY CLUSTERED ([ExperimentId] ASC),
CONSTRAINT [FK_Experiment_Bucket] FOREIGN KEY (BucketId) REFERENCES Bucket (BucketId)
);
I also have a Bucket table
CREATE TABLE [dbo].[Bucket] (
[BucketId] INT IDENTITY (1, 1) NOT NULL,
[BucketName] CHAR (1) NOT NULL,
CONSTRAINT [PK_BucketId] PRIMARY KEY CLUSTERED ([BucketId] ASC)
);
An experiment can have many buckets (A-Z), however, I'm not really sure how to insert the data.
I'm assuming I have to first insert the bucket information
INSERT INTO Bucket (BucketName) VALUES (#BucketName)
then I would have to insert the data in the experiment table. But how would I get the bucket id from the bucket table when populating the experiment table? Would I just need to do a select statement? Any help would be appreciated.

An experiment can have many buckets (A-Z)
Taking that into consideration, your foreign key is not correct.
You would like to have 1 experiment with N buckets.
In this example, you are having 1 experiment with 1 bucket.
In order to fix this, you'd need to modify Experiment, and remove the BucketId column.
In addition to that, you should add ExperimentId column to Bucket.
And of course, the foreign key constraint.
Once this is done, you will be able to have many buckets per experiment.
-
In order to add rows, you'd have to create the experiment first, and then as many buckets as you want.
Hope this helps.

If an experiment only has one bucket
Declare #bucketID Int;
INSERT INTO [Bucket] (BucketName) VALUES (#BucketName);
set #bucketID = (select SCOPE_IDENTITY());
insert into [Experiment] (bucketID) values (#bucketID);
But this has real problems as it creates a new bucket for each value without checking if the value exists.
What is the actual problem statement?
If this is what you want then just put BucketName in Experiment with no separate table or FK.
If you want an ID and A (as in one) BucketName then:
For this should declare a unique constraint on BucketName
Declare #bucketID Int;
set #bucketID = (select bucketID from bucket where BucketName = #BucketName);
if #bucketID = null;
begin
INSERT INTO [Bucket] (BucketName) VALUES (#BucketName);
set #bucketID = (select SCOPE_IDENTITY());
end
insert into [Experiment] (bucketID) values (#bucketID);
Below assumes a single experiment can have multiple buckets
In the current form it is not 3NF
You would have the problem of repeating data in Experiment and unique [ExperimentId] for each row.
You need a third table for the one to many relationship.
You need a 3rd table ExperimentBucket with a composite PK and FK reference to each table and remove BucketID from Experiment
CREATE TABLE [dbo].[ExperimentBucket] (
[BucketId] INT,
[ExperimentId] INT
CONSTRAINT [PK_BucketId] PRIMARY KEY CLUSTERED ([BucketId] ASC, [ExperimentId] ASC)
CONSTRAINT [FK_ExperimentBucket_Experiment] FOREIGN KEY (ExperimentId)
REFERENCES Experiment(ExperimentId)
CONSTRAINT [FK_ExperimentBucket_Bucket] FOREIGN KEY (BucketId)
REFERENCES Bucket(BucketId)
);

To begin, you have what we call a One-to-many foreign key relationship here: one experiment can have many buckets. In this case the way to set up the keys is that you have a foreign key in Bucket table which refers to the experiment ID.
Since the experiment can have more than one bucket, there will be one row in the experiment table that corresponds to many rows in the bucket table.
CREATE TABLE [dbo].[Experiment] (
[ExperimentId] INT IDENTITY (1, 1) NOT NULL,
[Experiment] VARCHAR (100) NOT NULL,
[Account] VARCHAR (100) NOT NULL,
[Profile] VARCHAR (100) NOT NULL,
[Property] VARCHAR (100) NOT NULL,
// No bucket id[BucketId] INT NULL,
CONSTRAINT [PK_Experiment] PRIMARY KEY CLUSTERED ([ExperimentId] ASC),
);
CREATE TABLE [dbo].[Bucket] (
[BucketId] INT IDENTITY (1, 1) NOT NULL,
[BucketName] CHAR (1) NOT NULL,
[ExperimentId] INT
CONSTRAINT [PK_BucketId] PRIMARY KEY CLUSTERED ([BucketId] ASC)
CONSTRAINT [FK_ExperimentBucket] FOREIGN KEY (ExperimentId)
REFERENCES Experiment(ExperimentId)
);
Once you have that, then you will just Insert the Experiment
INSERT INTO Experiment VALUES (your experiment data)
and then find out what experiment ID you ended up with
SELECT #experimentid = top 1 ExperimentID from Experiments order by ExperimentID
and then insert the buckets with the Bucket ID
INSERT INTO Buckets VALUES (your data with #experimentid)

Yes, you will do a sub-select to get the BucketId from the Bucket table while inserting to Experiment.
INSERT
...
(SELECT TOP 1 BucketId FROM Bucket WHERE BucketName=#BucketName)
...

Related

How to index a SQL table on a column in another table

I have the schema below - Let's pretend that there are 2 countries, A and B.
Country A has 1000 teams whereas country B has 100,000,000 - If I want to quickly query results based off which country the team is in, how would I construct my index?
Teams cannot change country if that helps.
Indexing a table depend upon knowing real schema.
For this simple table schema, I will create only Trusted FK between tables, at least this will be my first try.
Assuming Countryid,Teamid,Resultid are auto increment.
CREATE TABLE Country
(
id INT IDENTITY(1, 1) PRIMARY KEY,
CountryName VARCHAR(100) NOT NULL
);
CREATE TABLE Team
(
id INT IDENTITY(1, 1) PRIMARY KEY,
TeamName VARCHAR(100) NOT NULL,
CountryID INT NOT NULL
);
ALTER TABLE dbo.Team WITH CHECK
ADD CONSTRAINT FK_Team_CountryID
FOREIGN KEY(CountryID) REFERENCES dbo.Country(id);
ALTER TABLE dbo.Team WITH CHECK
CHECK CONSTRAINT FK_Team_CountryID;
--Just verify that newly created FK is trusted or not.
SELECT
name,
is_disabled,
is_not_trusted
FROM
sys.foreign_keys
WHERE
name = 'FK_Team_CountryID';
CREATE TABLE Result
(
id INT IDENTITY(1, 1) PRIMARY KEY,
TeamId INT NOT NULL,
Result INT NOT NULL
);
-- I have no idea how you are storing Result,so ignore it
ALTER TABLE dbo.Result WITH CHECK
ADD CONSTRAINT FK_Result_TeamId
FOREIGN KEY(TeamId) REFERENCES dbo.Team(id);
ALTER TABLE dbo.Result WITH CHECK
CHECK CONSTRAINT FK_Result_TeamId;
May be after seeing query plan of real query, I will De-normalise Result table to add Countryid , but for now it is not require since country table will be small

How do I insert data into a row in SQL?

I am following a tutorial and learning MVC from a book, where I was told to create a table using this script, which I did. But now I want to add an entire row to my Pet table, but I am unable to do it.
Script used to create all my tables.
CREATE TABLE [dbo].[Setting] (
[Id] INT NOT NULL IDENTITY(1, 1)
,[Key] VARCHAR(50) NOT NULL
,[Value] VARCHAR(500) NULL
,CONSTRAINT [PK_Setting] PRIMARY KEY ([Id])
);
CREATE TABLE [dbo].[PetType] (
[PetTypeID] INT NOT NULL IDENTITY(1, 1)
,[PetTypeDescription] VARCHAR(50) NULL
,CONSTRAINT [PK_PetType] PRIMARY KEY ([PetTypeID])
);
CREATE TABLE [dbo].[Status] (
[StatusID] INT NOT NULL IDENTITY(1, 1)
,[Description] VARCHAR(50) NOT NULL
,CONSTRAINT [PK_Status] PRIMARY KEY ([StatusID])
);
CREATE TABLE [dbo].[Pet] (
[PetID] INT NOT NULL IDENTITY(1, 1)
,[PetName] VARCHAR(100) NOT NULL
,[PetAgeYears] INT NULL
,[PetAgeMonths] INT NULL
,[StatusID] INT NOT NULL
,[LastSeenOn] DATE NULL
,[LastSeenWhere] VARCHAR(500) NULL
,[Notes] VARCHAR(1500) NULL
,[UserId] INT NOT NULL
,CONSTRAINT [PK_Pet] PRIMARY KEY ([PetID])
,CONSTRAINT [FK_Pet_Status] FOREIGN KEY ([StatusID]) REFERENCES [Status]([StatusID])
,CONSTRAINT [FK_Pet_User] FOREIGN KEY ([UserId]) REFERENCES [UserProfile]([UserId])
);
CREATE TABLE [dbo].[PetPhoto] (
[PhotoID] INT NOT NULL IDENTITY(1, 1)
,[PetID] INT NOT NULL
,[Photo] VARCHAR(500) NOT NULL CONSTRAINT [DF_PhotoFile] DEFAULT '/content/pets/no-image.png'
,[Notes] VARCHAR(500) NULL
,CONSTRAINT [PK_PetPhoto] PRIMARY KEY ([PhotoID])
,CONSTRAINT [FK_PetPhoto_Pet] FOREIGN KEY ([PetID]) REFERENCES [Pet]([PetID])
);
CREATE TABLE [dbo].[Message] (
[MessageID] INT NOT NULL
,[UserId] INT NOT NULL
,[MessageDate] DATETIME NOT NULL
,[From] VARCHAR(150) NOT NULL
,[Email] VARCHAR(150) NOT NULL
,[Subject] VARCHAR(150) NULL
,[Message] VARCHAR(1500) NOT NULL
,CONSTRAINT [PK_Message] PRIMARY KEY ([MessageID])
,CONSTRAINT [FK_Message_User] FOREIGN KEY ([UserId]) REFERENCES [UserProfile]([UserId])
);
I want to add some random values(for testing) into my Pet table's first row.
This is the Pet table's first row as an image for further clarity.
I tried using this script to add values to my table.
INSERT INTO Pet VALUES ('1', 'Fido', '12', '4', '1', '12/07/2004', 'New York', 'nothing', '1')
But I got an error saying
An explicit value for the identity column in table 'Pet' can only be specified when a column list is used and IDENTITY_INSERT is ON.
Now I am fairly new to SQL and I am unable to figure this out. I looked at other SO answers where people said something about SET IDENTITY_INSERT, but this didn't work for me as well. I believe I misunderstood other SO answer since I am fairly new to database languages. So need your help.
Thanks
In SQL Server identity is used for autoincrement. identity(1,1) means the starting value for the column will be 1 and will be incremented by 1. You can change it to desired value for example identity(5,2) starts the value at 5 and increments by 2. You no need to specify an explicit value for setting this column, it will be automatically assigned a unique value.
In mysql you can use AUTO_INCREMENT
Refer w3schools page for details sql autoincrement
PetID is defined as IDENTITY so you cannot specify a value to INSERT in that column unless you set "IDENTITY_INSERT" option to ON.
You have two options:
Dont specify that column/value and let SQL generate it for you.
Set IDENTITY_INSERT to ON before your INSERT operation.
Another very cool way to add rows/edit table (including editting deleting rows) is to use Microsoft SQL Management Studio Express. I didn't know about this until I'd been learning SQL for years. Basically expand the tree structure to the left, right-click on a table and choose Edit Table. When you get going with SQL more, you can edit Stored Procedures in here and pretty much anything SQL else you can can think of.
I've blurred out the actual database names but this gives you the gist of it :-

Two Composite Primary Key in SQL

I am trying to define table as follows:
CREATE TABLE dbo.[User]
(
Id int NOT NULL IDENTITY PRIMARY KEY,
Name nvarchar(1024) NOT NULL
);
CREATE TABLE [Group]
(
Id int NOT NULL IDENTITY PRIMARY KEY,
Name nvarchar(1024) NOT NULL
);
CREATE TABLE [UserToGroup]
(
Name VARCHER(20)
UserId int NOT NULL,
GroupId int NOT NULL,
PRIMARY KEY CLUSTERED ( UserId, Name),
PRIMARY KEY CLUSTERED ( GroupId, Name),
FOREIGN KEY ( UserId ) REFERENCES [User] ( Id ) ON UPDATE NO ACTION ON DELETE CASCADE,
FOREIGN KEY ( GroupId ) REFERENCES [Group] ( Id ) ON UPDATE NO ACTION ON DELETE CASCADE
);
How can i create table with two Composite Primary Key?
Name VARCHAR(20) NOT NULL,
UserId int NOT NULL,
GroupId int NOT NULL,
UNIQUE ( UserId, Name),
UNIQUE ( GroupId, Name)
In the relational model and in SQL there is no logical difference between one key and another so there's no very strong reason to have a different syntax for specifying one key over any other. However, for better or worse, the authors of the SQL standard decided to make a limitation that the PRIMARY KEY constraint syntax can only be used once per table and that where you need more than one key you have to use one or more UNIQUE constraints instead. Arguably it would be desirable to drop that limitation but since it's fundamentally just a bit of syntactical sugar that's unlikely to happen any time soon.

primary key of new row automatically goes to 2nd table where it's a foreign key in a new row

This is my 1st table
CREATE TABLE [dbo].[Booking_Date]
(
[Book_ID] INT IDENTITY (1, 1) NOT NULL,
[Book_Checkin_Date] DATETIME NULL,
[Book_Checkout_date] DATETIME NULL,
[Adults] INT NULL,
[Children] INT NULL,
CONSTRAINT [PK_Booking_Date]
PRIMARY KEY CLUSTERED ([Book_ID] ASC)
);
And this is my 2nd table
CREATE TABLE [dbo].[Room_Detail]
(
[R_D_ID] INT IDENTITY (1, 1) NOT NULL,
[Cust_ID] INT NULL,
[Book_ID] INT NULL,
[Room_ID] INT NULL,
[Room_Price] MONEY NULL,
PRIMARY KEY CLUSTERED ([R_D_ID] ASC),
CONSTRAINT [FK_Room_Detail_Customer]
FOREIGN KEY ([Cust_ID]) REFERENCES [dbo].[Customer] ([Cust_ID]),
CONSTRAINT [FK_Room_Detail_Booking_Date]
FOREIGN KEY ([Book_ID]) REFERENCES [dbo].[Booking_Date] ([Book_ID]),
CONSTRAINT [FK_Room_Detail_Room]
FOREIGN KEY ([Room_ID]) REFERENCES [dbo].[Room] ([Room_ID])
);
When I insert data into my 1st table a with booking date, then primary key of that data automatically is inserted into the 2nd table that is Room Detail in the Book_ID column
If you want to do this in T-SQL / SQL Server, you can use an AFTER INSERT trigger on the Booking_Date table - something like this:
CREATE TRIGGER trgInsertBookingDate
ON dbo.Booking_Date
AFTER INSERT
AS
-- for each row newly inserted into "Booking_Date",
-- insert a new (empty) row into "Room_Detail"
INSERT INTO dbo.Room_Detail(Book_ID)
SELECT i.Book_ID
FROM Inserted i
So every time you insert one or multiple row(s) into Booking_Date, a new (more or less empty) row will be inserted into Room_Detail for each of those new rows inserted. Since you don't have any other information available, you can only set the Book_ID column of Room_Detail in the trigger - the other columns will have to somehow be specified / filled later

Multilingual database design

I'm trying to design a database schema for a multilingual application. I have so far found a sample from this address. http://fczaja.blogspot.com/2010/08/multilanguage-database-design.html
But I haven't understood this sample. Should I insert Id value on app_product first? How can I know that these values are true for ProductId on app_product_translation?
CREATE TABLE ref_language (
Code Char(2)NOT NULL,
Name Varchar(20) NOT NULL,
PRIMARY KEY (Code)
);
CREATE TABLE app_product (
Id Int IDENTITY NOT NULL,
PRIMARY KEY (Id)
);
CREATE TABLE app_product_translation (
ProductId Int NOT NULL,
LanguageCode Char(2) NOT NULL,
Description Text NOT NULL,
FOREIGN KEY (ProductId) REFERENCES app_product(Id),
FOREIGN KEY (LanguageCode) REFERENCES ref_language(Code)
);
It looks like SQLServer code, proceeding on that assumption.
Yes you must insert the app_product first. But you cannot insert the id column's value. It is assigned automatically, because it is an identity column.
Two things you can check out...to find the identity column's value after inserting.
The OUTPUT clause of the INSERT statement. It can return any values that are inserted, not just the identity column.
The ##Identity variable. (by far more traditional and popular)
declare #lastid int
insert into x values (1,2,3)
set #lastid = ##identity
insert into y values (#lastid, a, b, c)