0

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.

Becuzz
  • 6,846
  • 26
  • 39
  • As others have noted, you have not set up your tables correctly if one experiment can have many buckets. Please re-visit and edit your question accordingly. It's causing a lot of distress in commenters who think they can read your mind. – Tab Alleman Sep 23 '14 at 20:26
  • Don't post a vague question and not respond to questions for 8 hours. -1 – paparazzo Sep 24 '14 at 03:11

4 Answers4

0

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.

0

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)
);
paparazzo
  • 44,497
  • 23
  • 105
  • 176
-1

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)
Patrick
  • 416
  • 3
  • 7
  • 2
    How will the `SELECT @experimentid = ExperimentID from Experiments` work? Why not use `SCOPE_IDENTITY()`? – ypercubeᵀᴹ Sep 23 '14 at 19:57
  • No he does not have a 1 to many and neither do you. That PK only allows one row. Even if you make a composite PK you have the problem of repeating [BucketName] which is not 3NF. I did not vote you down. – paparazzo Sep 23 '14 at 20:15
  • @Blam This answer does have 1-to-many between `Experiment` and `Bucket` (the `FK_Experiment_Bucket` is obviously left there by mistake.) – ypercubeᵀᴹ Sep 23 '14 at 20:20
  • @ypercube OK it is 1 to many. I did not vote it down. But it allows duplicate BucketName which I doubt is the intent of question even though not in the question. – paparazzo Sep 23 '14 at 20:24
  • I agree that this coe allows duplicate bucket name, but there may be cases where this is useful, the question did not indicate that bucket names must be unique. SCOPE_IDENTITY() is a good option instead of selecting the expemimentId. And yes the FK_experiment_bucket was left in error. I will remove – Patrick Sep 23 '14 at 20:37
-3

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)
...
Tab Alleman
  • 31,483
  • 7
  • 36
  • 52
  • 3
    `BucketName` is not unique. Which ID will you get when you request a bucketname which matches 2 or more rows? – ypercubeᵀᴹ Sep 23 '14 at 19:34
  • 1
    TOP 1 without ORDER BY? You know there are reliable ways to retrieve the IDENTITY value you just inserted, and that's not one them. – Aaron Bertrand Sep 23 '14 at 20:10
  • The OP never specifies that he will always want to get the most recently inserted Bucket, which is why I discarded solutions involving IDENTITY. He doesn't specify that Bucketname is unique, true, but it would be poor design if it weren't, because like you said, which BucketId do you want if there are dupe names? That would be a question for OP, but at least with TOP 1 the sub-select won't error. – Tab Alleman Sep 23 '14 at 20:12
  • That's correct, but still a hack. A correct approach would be TOP with ORDER BY. But what's wrong with SCOPE_IDENTITY(), @@IDENTITY, IDENT_CURRENT(‘tablename’) in that context? – Marian Sep 23 '14 at 22:34
  • And what would I suggest for an ORDER BY without being able to read the OP's mind? Again I think you also are making assumptions about the desired solution that are not supported by the text of the original question. – Tab Alleman Sep 24 '14 at 12:42