Instead of Trigger using dynamic sequences SQL Server - sql-server

I want to auto generate sequence_id dynamically using sequences.
I have sequences seq_C1, seq_C2, seq_C3,.... like this. The next value of these sequences are provided below.
seq_C1: next value would be 121
seq_C2: next value would be 76
seq_C3: next value would be 2981
.....
.....
Sample data in the source_table:
ID Name
1 C1
2 C1
3 C2
4 C2
5 C3
...
...
I have to auto increment sequence_id column based on the name column using sequence (dynamically).
The target table should be populated like this
ID Name sequence_id
1 C1 121
2 C1 122
3 C2 76
4 C2 77
5 C3 2981
...
...
The target table is populated using select...insert statement using a stored procedure. There are around 100 to 1000 rows inserted to target using source table during single stored procedure call.
I created an instead of trigger to do this.
I tried the below SQL in the trigger but I got the error
Invalid object name 'seq_'.
Code:
insert into target_table
select
id, name, (NEXT VALUE FOR 'seq_' + NAME)
from INSERTED
I am hitting my heads and struggling for the past two days. Kindly provide any suggestions to implement this. I am using SQL Server 2012.

I think the best you can do is something like this:
insert into target_table
select id,name, NEXT VALUE FOR seq_C1 from INSERTED where name='C1'
union all
select id,name, NEXT VALUE FOR seq_C2 from INSERTED where name='C2'
union all
select id,name, NEXT VALUE FOR seq_C3 from INSERTED where name='C3'
And hope that adding new sequences is a rare thing.

Related

tableau custom sql pivot

I have a SQL Server data source that I cannot change the structure of.
I have started pivoting the data with CustomSQL query below, but I need to modify the query so that when iterations 3, 4 ,5 ...n data are added to the source in the future, it automatically includes it in the pivoted data. I don't want to have to keep updating the query. Any ideas?
KPI Name Iteration 1 Iteration 2
a 1 2
b 50 51
Select [KPI]
, 'Iteration1' as [Iteration]
, [Iteration1] as [Count]
From [MC_KPI]
Union ALL
Select [KPI]
, 'Iteration2' as [Iteration]
, [Iteration2] as [Count]
From [KPI]
Now I have this
KPI Name Iteration 1 Iteration 2
a 1 1
a 2 2
b 1 50
b 2 51
What you are doing is called "unpivot" in SQL Server. You can see the description here:
https://learn.microsoft.com/en-us/sql/t-sql/queries/from-using-pivot-and-unpivot?view=sql-server-2017
If you want to be able to add iterations without having to modify something in tableau, you can create a view in SQL that does unpivot and just do "select * from view" in tableau. This would give you the chance to change the view under the covers from tableau and have things continue to work (since the unpivot output is just a property bag and the columns are not really changing as you add properties into the output)

Clone row and maintain a reference to cloned row

I want to clone some row from a table, the row must be selected using a specific condition, but I also need to save in a temporary table N pair(sourceRowID, destinationRowID)
I've tried using OUTPUT but I can't use fields of the source row
INSERT INTO myTable(Value1, Value2)
OUTPUT myTable.ID, Inserted.ID
INTO #tempTable(sourceRowID, destinationRowID)
SELECT Value1, Value2
FROM myTable
WHERE Value2 > 10
Is there a solution to this? Unfortunately I am constraint to use SQL server 2008
UPDATE:
For now this is my solution:
First of all I write the inserted record using the OUTPUT instruction to the #tempTable ensuring that the records are inserted ordered by ID
At this point I've the #tempTable that contains, for example
sourceRowID | destinationRowID
-------------------------------
NULL | 12
NULL | 15
NULL | 16
NULL | 23
than I update #tempTable retrieving again the same record with the same WHERE condition joining the #tempTable and the retrieved record by RowNumber ensuring again that the records are retrieved ordered by destinationRowID, in this way the order of new and old record must be the same, and with the update I'll obtain the #tempTable with correct sourceRowID and destinationRowID

How to configure a table column in TSQL that works as a sequence depending on the values of another two columns?

I have a table that looks like this:
ID A B Count
-----------------
1 abc 0 1
2 abc 0 2
3 abc 1 1
4 xyz 1 1
5 xyz 1 2
6 xyz 1 3
7 abc 1 2
8 abc 0 3
The "Count" column is incremented by one in the next insertion depending on the value of fields "A" and "B". so for example, if the next record I want to insert is:
ID A B Count
-----------------
abc 0
The value of count will be 4.
I have been trying to find documentation about this, but I'm still quite lost in the MS SQL world! There must be a way to configure the "Count" column as a sequence dependent on the other two columns. My alternative would be to select all the records with A=abc and B=0, get the maximum "Count", and do +1 in the latest one, but I suspect there must be another way related to properly defining the Count column when creating the table.
The first question is: Why do you need this?
There is ROW_NUMBER() which will - provided the correct PARTITION BY in the OVER() clause - do this for you:
DECLARE #tbl TABLE(ID INT,A VARCHAR(10),B INT);
INSERT INTO #tbl VALUES
(1,'abc',0)
,(2,'abc',0)
,(3,'abc',1)
,(4,'xyz',1)
,(5,'xyz',1)
,(6,'xyz',1)
,(7,'abc',1)
,(8,'abc',0);
SELECT *
,ROW_NUMBER() OVER(PARTITION BY A,B ORDER BY ID)
FROM #tbl
ORDER BY ID;
The problem is: What happens if a row is changed or deleted?
If you write this values into a persistant column and one row is removed physically, you'll have a gap. Okay, one can live with this... But if a value in A is changed from abc to xyz (same applies to B of course) the whole approach breaks.
If you still want to write this into a column you can use the ROW_NUMBER() from above to fill these values initially and a TRIGGER to set the next value with your SELECT MAX()+1 approach for new rows.
If the set of combinations is limited you might create a SEQUENCE (needs v2012+) for each.
But - to be honest - the whole issue smells a bit.

Why is this stored procedure using TOP 100 PERCENT?

I have the following stored procedure inside a third party application inside sql server 2008 R2:-
ALTER PROCEDURE [dbo].[GetContacts]
AS
BEGIN
---------
SELECT TOP (100) PERCENT .....
INTO [#temp200]
FROM dbo.Contact
ORDER BY dbo.Contact.Name
--SELECT * from #temp200
SELECT top 38 *
FROM #temp200
ORDER BY Fullname
delete top (38) FROM #temp200
SELECT top 38 *
FROM #temp200
ORDER BY Fullname
delete top (38) FROM #temp200
SELECT top 38 *
FROM #temp200
ORDER BY Fullname
delete top (38) FROM #temp200
SELECT *
FROM #temp200
ORDER BY Fullname
now I run this inside sql management studio where I got the following results tabs:-
the first one contains 38 records.
the second one 38 records.
the third one contains 38 records.
the fourth one contains 30 records.
where in this case I got 144 records ,, so not sure what is the purpose of the
(SELECT TOP (100)) , as I will get 144 records. now as a test I changed the Select TOP(100) to be Select TOP(35) where in this case I got 2 results; the first on with 38 records while the second one with 17 records and .. so can anyone advice how my above SP is working ?
That guy did not understand that tables do not have order. He tried to insert in an ordered way into the temp tables. This is not possible. The TOP 100 PERCENT trick shuts up the warning about that but does nothing to ensure order.
In earlier SQL Server versions this code might well have worked by coincidence. Since then more optimizations have been added and this code is extremely brittle. Rewrite this if you get the chance. It's a latent time bomb.

Comparing data in two tables,insert if data is not there,update if data is there

I have two tables
SELECT * FROM dbo.VMM_Table_20120210 table 1
and output of this table is
vehicle_Make vehicle_model
---------------------------
01 000
01 111
01 112
01 113
01 114
01 115
01 117
like this upto 993 records r there in the above table
and 2nd table is
SELECT * FROM dbo.TBL_VEHICLE_MODEL_NEW
and output of this table is
vmodel_id vmodel_vmake_code vmodel_type vmodel_code
---------------------------------------------------------------------------
1 01 t 7AV
2 01 c 7AE
UPTO 1107 records are there in this table
the requirement is I need to compare vehicle_make with vmodel_vmake_code and vehicle_model with vmodel_code and If data is not there in the 2nd table I need to insert it from the first table if data is there I need to update the data
I need it procedure with cursor in the procedure to loop the each row will u please help me in this situation
I am assuming that your tags are for SQL-Server, and not SQL and Server separately, so I am going to suggest the MERGE operation. There are some details that are pretty unclear from the question, such as what Update to perform when there is a match, and how to get values for vmodel_type and vmodel_Code, so I can't provide a perfect answer, but this should get you started:
MERGE INTO dbo.TBL_VEHICLE_MODEL_NEW t
USING dbo.VMM_Table_20120210 c
ON t.vmodel_vmake_code = c.vehicle_Make AND t.vmodel_code = c.vehicle_model
WHEN MATCHED THEN
UPDATE SET vmodel_type = 'A' -- CHANGE TO WHATEVER YOU WANT TO HAPPEN WHEN THE DATA EXISTS IN TABLE 2
WHEN NOT MATCHED THEN
INSERT VALUES (c.Vehicle_Make, c.Vehicle_Model, 't', '7AV');
-- WHATEVER YOU WANT TO HAPPEN WHEN THE RECORD IN TABLE 1 DOES NOT EXIST IN TABLE 2
See MSDN for more on MERGE.

Resources