T/SQL - Semi-manual Identity Column Insertion - sql

Initial Query
DECLARE #Table1 TABLE (ID int, Value varchar(50))
DECLARE #Table2 TABLE (Value varchar(50))
DECLARE #MaxID1 int
DECLARE #MaxID2 int = 52
INSERT INTO #Table1 (ID, Value)
Values (1,'One'),(2,'Two'),(3,'Three'),(4,'Four'),(5,'Five')
INSERT INTO #Table2 (Value)
Values ('Six'),('Seven'),('Eight'),('Nine'),('Ten')
SELECT * FROM #Table1
SELECT * FROM #Table2
SELECT #MaxID1 = MAX(ID) FROM #Table1
SELECT #MaxID1 Scenario1, #MaxID2 Scenario2
Expected Outcome of #Table1 after inserting values (Value field) from #Table2
// (Scenario #1 using #MaxID1)
ID Value
1 One
2 Two
3 Three
4 Four
5 Five
6 Six
7 Seven
8 Eight
9 Nine
10 Ten
// (Scenario #2 using #MaxID2)
ID Value
1 One
2 Two
3 Three
4 Four
5 Five
52 Six
53 Seven
54 Eight
55 Nine
56 Ten
How do I semi-manually insert ID values into an Identity column (ID) while executing INSERT query on that table (#Table1) from another table (#Table2)? In the first scenario, I wish to take the Max(ID) from #Table1 and add 1 to it and keep adding records. In the second scenario, I wish to take a predefined # and then start adding a record where first new record's ID would be the predefined values and all subsequent new records would be Max(ID) + 1.
Thank you
UPDATED #Table 1 does NOT have identity constraint.

If you want to insert an arbitrary int value into an identity column, use IDENTITY_INSERT:
SET IDENTITY_INSERT [table_name] ON;
Only one table at a time for a given session can have this property on. Make sure you turn it off when done:
SET IDENTITY_INSERT [table_name] OFF;

Related

ignoring last value if its the same as current value

I have an table where i would like to query the following:
The data comes in batches . This data is combined with an id.
This ID only gets send ones when the new batch comes in. After that the ID only changes when there is a new batch . In the mean time the value stays null
What i need to do is if new data comes in and it has the same id as the previous batch i have to continue the insert with null in the id field instead of pushing a new row with the same id value.
Beneath is a simplistic view of the table
ID Values
1 10
null 20
null 20
null 20
null 20
2 20
null 20
null 20
null 20
null 20
1 20
null 20
If you could help me point in a directions that would help me a lot.
Maybe to clearify the id value is a set of tags. So there are some definied tags(100 or more) and when a new batch comes the batch gets a tag with it. And if that tag is the same as the previous the null has to continue instead of inserting the same tag
You'll need to add an identity field (or a timestamp) in order to be able to query the latest ID.
ALTER TABLE MyTable ADD MyIdent INT IDENTITY(1, 1) NOT NULL
Then on your insert (if your Id value is NULL) you can call
INSERT INTO MyTable (Id, Values)
SELECT TOP 1 Id, #ValuesVariable
FROM MyTable
WHERE Id IS NOT NULL
ORDER BY MyIdent DESC
This below Sp may helps to inert data try this
IF OBJECT_ID('tempdb..#Temp')IS NOT NULL
DROP TABLE #Temp
CREATE TABLE #Temp (ID INT,[Values] INT)
CREATE PROCEDURE usp_Insert
(
#Id INT,
#Values INT
)
AS
BEGIN
IF NOT EXISTS (SELECT 1 FROM #Temp WHERE ID = #ID)
BEGIN
INSERT INTO #Temp(ID,[Values])
SELECT #Id,#Values
END
ELSE
INSERT INTO #Temp(ID,[Values])
SELECT NULL,#Values
END
EXEC usp_Insert 2,12
SELECT * FROM #Temp

Know identity before insert

I want to copy rows from the table within the table itself. But before inserting I need to modify a varchar column appending the value of identity column to it.
My table structure is:
secID docID secName secType secBor
1 5 sec-1 G 9
2 5 sec-2 H 12
3 5 sec-3 G 12
4 7 sec-4 G 12
5 7 sec-5 H 9
If I want to copy data of say docID 5, currently this runs through a loop one row at a time.
I can write my query as
insert into tableA (docID, secName, secType, secBor)
select 8, secName, secType, secBor from tableA where docID = 5
But how can I set value of secName before hand so that it becomes sec-<value of secID column>?
Don't try to guess the value of identity column. In your case you could simply create a computed column secName AS CONCAT('sec-', secID). There is no further need to update that column.
DB Fiddle
It is also possible to create an AFTER INSERT trigger to update the column.
Since SQL Server does not have GENERATED ALWAYS AS ('Sec - ' + id) the only simple option I see is to use a trigger.
Adding to my comment something like:
insert into tableA (docID, secName, secType, secBor)
select
ROW_NUMBER() OVER (ORDER BY DocID),
'Sec -'+ ROW_NUMBER() OVER (ORDER BY DocID),
secType, secBor
from tableA
where docID = 5
In SQL Server 2012 and later, you can achieve this by using the new sequence object.
CREATE SEQUENCE TableAIdentitySeqeunce
START WITH 1
INCREMENT BY 1 ;
GO
create table TableA
(
secId int default (NEXT VALUE FOR TableAIdentitySeqeunce) not null primary key,
varcharCol nvarchar(50)
)
declare #nextId int;
select #nextId = NEXT VALUE FOR TableAIdentitySeqeunce
insert TableA (secId, varcharCol)
values (#nextId, N'Data #' + cast(#nextId as nvarchar(50)))

Insert from select on same table and store old and new identity values in separate table

Temporary table:
declare #Temp_Table table
(
newSID int,
oldSID int
)
Database table: Solutions
Solutions:
* 1 solution1 111
* 2 solution2 111
* 3 solution3 111
After insert,
* 1 solution1 111
* 2 solution2 111
* 3 solution3 111
* 4 solution1 222
* 5 solution2 222
* 6 solution3 222
temp table Expected
oldsID NewSID
* 1 4
* 2 5
* 3 6
This table has SID (identity), SName and cnumber.
Now I want to select some rows from the Solutions table and insert their values into same table.
When inserting each row I want to store the old identity value and new identity value in the temporary table (#Temp_Table).
Please help me with this.
The trick is to use merge instead of a regular insert into..select, since with merge you can use data from both the source and the target in the output clause.
First, create and populate sample table (Please save us this step in your future questions):
CREATE TABLE Solutions
(
SolutionID int identity (1,1),
SolutionName varchar(10),
ClientNumber int
)
INSERT INTO Solutions (SolutionName, ClientNumber) VALUES
('solution1', 111),
('solution2', 111),
('solution3', 111)
Then, declare the mapping table:
DECLARE #Temp_MasterSolutionsTable AS TABLE
(
newSolutionID int,
oldSolutionID int
)
Next, Copy the records you want:
MERGE INTO Solutions USING
(
SELECT SolutionID, SolutionName, ClientNumber
FROM Solutions
--WHERE CONDITION -- I'm guessing you will need a where clause here
) AS s ON 1 = 0 -- Always not matched
WHEN NOT MATCHED THEN
INSERT (SolutionName, ClientNumber)
VALUES (s.SolutionName, s.ClientNumber)
-- and here is where the magic happens
OUTPUT Inserted.SolutionID, s.SolutionID
INTO #Temp_MasterSolutionsTable (newSolutionID, oldSolutionID);
See a live demo on rextester.

Random Function behavior in SELECT query in SQL Server

I have a written a random function dbo.UDF_Q_RandomNumber() that generates a floating type random number between 0 and 1.
DECLARE #upper = 10
DECLARE #lower = 1
SELECT
ROUND(CAST((#lower + (#upper - #lower) * dbo.UDF_Q_RandomNumber()) AS INT), 0)
The above code generates a random number between 1 and 10.
Now I created a temporary table #tempTable with 10 rows in it with columns Id and Number.
Id Number
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 10
SQL query:
CREATE TABLE #tempTable(Id INT, Number INT)
INSERT INTO #tempTable VALUES (1,1)
INSERT INTO #tempTable VALUES (2,2)
INSERT INTO #tempTable VALUES (3,3)
INSERT INTO #tempTable VALUES (4,4)
INSERT INTO #tempTable VALUES (5,5)
INSERT INTO #tempTable VALUES (6,6)
INSERT INTO #tempTable VALUES (7,7)
INSERT INTO #tempTable VALUES (8,8)
INSERT INTO #tempTable VALUES (9,9)
INSERT INTO #tempTable VALUES (10,10)
DECLARE #maxCount INT;
SELECT #maxCount= COUNT(1) FROM #tempTable
SELECT * FROM #tempTable
SELECT Number
FROM #tempTable
WHERE Id = ROUND(CAST((1+(#maxCount-1)*dbo.UDF_Q_RandomNumber())AS INT),0)
DROP TABLE #tempTable
Here the query
SELECT Number
FROM #tempTable
WHERE Id = ROUND(CAST((1+(#maxCount-1)*dbo.UDF_Q_RandomNumber()) AS INT), 0)
Sometimes it returns 2 rows and sometimes null which should not come as Id selected is between 1 and 10 (the rows in temptable) and every Id has value too.
Please help .
Without seeing the function, it's hard to say, but I suspect your function is non-deterministic, so it gets interpreted for each row of the table.
If you use rand() it only returns one row
SELECT Number FROM #tempTable WHERE Id= ROUND(CAST((1+(#maxCount-1)*rand())AS INT),0)
Alternatively, if you just want a random #n rows...
select top (#n) * from #tempTable order by newid()

Loop through rows and add a number for a column for each of them automatically in SQL Server

I have got an over 500 rows table with a column called ID which is of datetype INT. Currently the values are all NULL.
What I want to achieve is to populate the ID column with an incremental number for each row, say 1, 2, 3, 4, ..., 500 etc.
Please give me a help with any idea how to achieve this by SQL script.
using ROW_NUMBER in a CTE is one way, but here's an alternative; Create a new id1 column as int identity(1,1), then copy over to id, then drop id1:
-- sample table
create table myTable(id int, value varchar(100));
-- populate 10 rows with just the value column
insert into myTable(value)
select top 10 'some data'
from sys.messages;
go
-- now populate id with sequential integers
alter table myTable add id1 int identity(1,1)
go
update myTable set id=id1;
go
alter table myTable drop column id1;
go
select * from myTable
Result:
id value
----------- -------------
1 some data
2 some data
3 some data
4 some data
5 some data
6 some data
7 some data
8 some data
9 some data
10 some data
While you could also drop and recreate ID as an identity, it would lose its ordinal position, hence the temporary id1 column.
#create one temporary table
CREATE TABLE Tmp
(
ID int NOT NULL
IDENTITY(1, 1),
field(s) datatype NULL
)
#suppose your old table name is tbl,now pull
#Id will be auto-increment here
#dont select Id here as it is Null
INSERT INTO Tmp (field(s) )
SELECT
field(s)
FROM tbl
#drop current table
DROP TABLE tbl
#rename temp table to current one
Exec sp_rename 'Tmp', 'tbl'
#drop your temp table
#write alter command to set identitry to Id of current table
good luck