I have a small SQL based challenge that i’m trying to solve to better my knowledge of Dynamic SQL.
My requirements are as follows.
I created a table that looks as follows:
CREATE TABLE Prison_Doors
(
DoorNum INT IDENTITY(1,1) PRIMARY KEY,
DoorOpen BIT,
DoorClosed BIT,
Trips INT
)
GO
I need to Create a Dynamic SQL Proc to insert 50 Door numbers and assign them as closed.
Expected result of proc:
|DoorNum|DoorOpen|DoorClosed|Trips|
|-------|--------|----------|-----|
| 1 | 0 | 1 |null |
|-------|--------|----------|-----|
|---------All the way to 50-------|
|-------|--------|----------|-----|
| 50 | 0 | 1 |null |
This is what I have written but it is not inserting:
BEGIN
DECLARE @SQL VARCHAR(8000)
DECLARE @Index INT
SET @Index=1
WHILE (@Index<=50)
BEGIN
SET @SQL= 'INSERT INTO Prison_Doors(DoorNum,DoorOpen,DoorClosed)
VALUES('+CAST(@Index AS VARCHAR)+',0,1),'
SET @Index=@Index+1
END
SET @SQL = SUBSTRING(@SQL, 1, LEN(@SQL)-1)
EXEC(@SQL)
END
I would like to know what I am doing wrong.
after all of this is done I then need to run another loop to start at door one and change every second door to open and change trips to one and then increment to every 3 doors to open and trips becomes 2 and this incrementation continues until all doors are open which will then select the number of trips that it took.
I hope somebody can assist me with this as I am new to Dynamic SQL and I just need some guidance and not the complete solution.
Help is much appreciated 🙂
The error you got is because you are trying to insert into an identity column
DoorNumber:Remove that columns from the column list, instead of:
remove that column
DoorNum:However, there is no need for dynamic SQL to do that, you can do this using an anchor table like this:
Live Demo.
Update:
What my code does line by line?
Generating Sequence of numbers:
The first problem was generating a sequence of 50 numbers from 1 to 50, I used an anchor table with only four rows from 1 to 4 like this:
This syntax using the
VALUESis new to SQL-Server-2008, it is called Row Value Constructor. After theVALUES, you assign an alias of the table and the target columns in parentheses liketemp(n).For old versions you have to use something like :
This will give you only 4 rows, but we need to generate 50. Thats why I
CROSS JOINthis table three time with itself using:It is the same as
This will multiply these rows 64 times, 4 rows3 = 64 rows:
The Use Of
ROW_NUMBER()Function:Then using the
ROW_NUMBER()will give us a ranking number from 1 to 64 like this:Note that:
ROW_NUMBERrequires anORDER BYclause, in or case it doesn’t matter the order, so I used(SELECT 1).There is also another way for generating a sequence numbers with out the use of
ROW_NUMBER, it also depends on theCROSS JOIN, with an anchor table like:Another Way of Generating Sequence Of Numbers
Common Table Expressions:
The CTE is called common table expression, and it was introdeced in SQL Server 2005. It is one of the table expressions types that SQL Server supports. The other three are:
It has a lot of important advantages. One of them is let you create a virtual tables that you can reuse them later, like what I did:
Here I defined two CTE’s
tempthen another onenumsthat ruse thattempso this OL, you can create multiple CTE’s, just put a semicolon, then a new one with theASclause and two().Insert into one table from another table using
INSERT INTO ... SELECT ...Now, we have a virtual table
numshaving rows from 1 to 64, we need to insert the rows from 1 to 50.For this, you can use the
INSERT INTO ... SELECT ....Note that the columns in the
INSERTclause are optional, but If you do so, you have to put a value for each row, if not you will got an error, for example if you have four columns and you put only three values in theVALUESclause or in theSELECTclause, then you will got an error. This is not valid for the idenetityt columns which are defined with:In this case you simply ignore that column in the columns list in the
INSERTclause and it will have the identity value. There is an option that let you insert a value manually like in the @Raj’s answer.Note that: In my answer, I am not inserting the sequence numbers in to that column instead, inserting the values 50 times. But the actual numbers are generating automatically because of the Identity column: