How to insert a new field and Toggle its value - sql

I have a table name MyDBTbl.
Name DisplayOrder
---------------------------
Home 1
Products 2
Contact true
Career false
I want to insert a new property Qualification with default value True. And when user run the script again it will check the existence of property , if Not present insert it and if Present toggle its value to false and vise versa.

Create Table Initially in your database
CREATE TABLE Tempdata(Name VARCHAR(20), DisplayOrder VARCHAR(20))
INSERT INTO Tempdata
SELECT'Home' ,'1' UNION ALL
SELECT'Products' ,'2' UNION ALL
SELECT'Contact' ,'true' UNION ALL
SELECT'Career' ,'false'
Run this below sql script for your the requirement and written code just based on requirement, i think it will be helpful to you
IF NOT EXISTS(SELECT 1 FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME='Tempdata')
BEGIN
CREATE TABLE Tempdata(Name VARCHAR(20), DisplayOrder VARCHAR(20))
INSERT INTO Tempdata
SELECT'Home' ,'1' UNION ALL
SELECT'Products' ,'2' UNION ALL
SELECT'Contact' ,'true' UNION ALL
SELECT'Career' ,'false'
END
--DROP TABLE Tempdata
IF EXISTS(SELECT 1 FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME='Tempdata')
BEGIN
IF NOT EXISTS(SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME='Tempdata' AND COLUMN_NAME='Qualification')
BEGIN
ALTER TABLE Tempdata ADD Qualification VARCHAR(10) NULL
ALTER TABLE Tempdata ADD CONSTRAINT Df_Qualification DEFAULT('True') FOR Qualification
UPDATE Tempdata SET Qualification='True'
END
ELSE
IF EXISTS(SELECT 1 FROM Tempdata
WHERE Qualification='True'
)
BEGIN
UPDATE Tempdata SET Qualification='False'
END
ELSE UPDATE Tempdata SET Qualification='True'
END
SELECT * FROM Tempdata

Related

Using the identity column to add a value to a computed column

At times I need to store a temporary value to a field. I have a stored procedure that adds it using:
Insert new record first then
SELECT #Record_Value = SCOPE_IDENTITY();
UPDATE ADMIN_Publication_JSON
SET NonPubID = CAST(#Record_Value as nvarchar(20)) + '_tmp'
WHERE RecID = #Record_Value
It simply takes the identity value and adds an '_tmp' to the end. Is there a way that I can create a default value in the table that would do that automatically if I did not insert a value into that field?
The NonPubID column is just a NVARCHAR(50).
Thanks
You could write a trigger, that replaces NULL with that string upon INSERT.
CREATE TRIGGER admin_publication_json_bi
ON admin_publication_json
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
UPDATE apj
SET apj.nonpubid = concat(convert(varchar(20), i.id), '_tmp')
FROM admin_publication_json apj
INNER JOIN inserted i
ON i.id = apj.id
WHERE i.nonpubid IS NULL;
END;
db<>fiddle
Downside: You cannot explicitly insert NULLs for that column, should that be desired.
Check out NewKey col below:
CREATE TABLE #Table
(
ID INT NOT NULL IDENTITY(1,1) PRIMARY KEY CLUSTERED,
IDValue VARCHAR(1) ,
ModifiedDT DATETIME NULL,
NewKey AS ( CONVERT(VARCHAR(100),ID)+'_Tmp' )
)
INSERT #Table( IDValue, ModifiedDT )
SELECT 'A', GETDATE()
UNION ALL
SELECT 'Y', GETDATE() - 1
UNION ALL
SELECT 'N', GETDATE() - 5
SELECT * FROM #Table

SQL Server T-SQL query to add to a column if query returns resultset

Ok so I'm trying to tie two queries together through a cursor.
I create a temp table for name (varchar) and count (int).
The first query grabs a name and a versionnumber, if that versionnumber = a certain version it adds the name (varchar) and a 1 (int) to the temp table.
Next I want to have a different query look for a specific privileged for the same name as the first query, if that privilege = a certain privilege then add another 1 to the count column of the temp table.
Thus leaving me with a record in the table with a name and a 2 in the count column.
What I have so far is this:
CREATE TABLE #temptable
(
name varchar(10)
acount int
)
DECLARE #name nvarchar(10)
DECLARE #acount int
SET #acount = 0
DECLARE name_cursor CURSOR FOR
SELECT DISTINCT NAME
FROM atable
OPEN name_cursor
FETCH NEXT FROM name_cursor INTO #name
WHILE ##FETCH_STATUS = 0
BEGIN
INSERT INTO #temptable (name, acount)
WHILE(SELECT DISTINCT name, version
FROM atable
WHERE version = 'specificversion') IS NOT NULL
BEGIN
SET #acount = #acount + 1
END
WHILE(SELECT DISTINCT name, priviledge
FROM atable
WHERE priviledge = 'specifiedpriviledge') IS NOT NULL
BEGIN
SET #acount = #acount + 1
END
SELECT #name, #acount
END
CLOSE name_cursor
DEALLOCATE name_cursor
I'm going to guess at your table structure and desired result a bit, but I don't think you need a cursor here. Here's what I tried:
--Test rig
create table #atable
(
name varchar(10),
versionnum varchar(10),
privilege varchar(10)
)
insert into #atable (name, versionnum, privilege)
values
('Tim', 'A', 'Level 1'),
('Tim', 'B', 'Level 2'),
('Charles', 'A', 'Level 1'),
('Alex', 'C', 'Level 2')
--End Test Rig
CREATE TABLE #temptable
(
name varchar(10),
acount int
)
insert into #temptable (name, acount)
select distinct name, 0 from #atable
update #temptable
set acount = acount+1
where #temptable.name in (select name from #atable where #atable.versionnum = 'A')
update #temptable
set acount = acount+1
where #temptable.name in (select name from #atable where #atable.privilege = 'Level 2')
select * from #atable
select * from #temptable
drop table #temptable
drop table #atable
This got me
Alex 1
Charles 1
Tim 2
Which is what I assume you wanted. Tim has an entry with a Version of A and also has an entry with a Privilege of Level 2, even though they're different entries. Charles has one with Version A, and Alex has one with a Privilege of Level 2. Is that about what you were looking for?

SQL Server 2008: Sql Insert/Update into another table using insertion IDs output from another table

I have a procedure for insert in multiple dependent tables (update in case record exist). I have input parameters as comma separated string which I am reading in table.
After 1st insertion I am getting InsertedIds in another table variable.
I am struggling over how to do insert in 2nd table. I have following input parameters for 2nd table:
Declare #IdsToBeUpdated table (primary key identity pkey, id int) -- values are 1,-1,3,-1
Declare #CommentsTobeInserted table( primary key identity pkey, comment varchar (max)) -- values are 'com1', 'com2', 'com3'
-1 input in table #IdsToBeUpdated depicts insertion for the corresponding rows in all input tables and value other than -1 depicts that records at that pkey value in all other tables (#CommentsTobeInserted table as in example) have to be updated.
So after first insertion I am getting the inserted ids for rows with -1 value. #InsertedIds = 4,5
So my Ids list logically would become.. 1,4,3,5.
But I am stuck now how to insert/update records in second table respectively.
2nd table would be like follows:
Pkey Primary key identity, commentIds(coming from inserted ids and #IdsToBeUpdated), comments.
I have added one more InsertedIds column in #CommentsTobeInserted. If I could fill it with right InsertedId against correct row, I guess I would be able to do insert/update in 2nd table. And where the value is Id in new column I would do insert, where it's null, I would perform update using #IdsToBeUpdated table.
But currently none of my approach is working. I am new to SQL. Any help would be highly appreciated.
Following is some portion of script for better understanding. I have added first insertion script as well.
USE [Demo]
GO
/****** Object: StoredProcedure [dbo].[USP_NewRequest_Insert] Script Date: 2/11/2016 2:50:34 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[USP_NewRequest_Insert]
-----------------------------------
--------- SomeInput parameters
---------for first insertion omitted
--------------------------------
#IdsToBeUpdated varchar(MAX), --Values are 23|-1|32|-1|-1
#CommentList AS VARCHAR(MAX), --Values 'C2'|'C4'|'C5'|'C6'|'C7'
#MCodeList VARCHAR(MAX), --Values 'M2'|'M4'|'M5'|'M6'|'M7'
#CustomerIdsList VARCHAR(MAX), ----Values 'Cust2'|'Cust4'|'Cust5'|'Cust6'|'Cust7'
#ReturnValue AS INT OUTPUT,
------------------Data is in the order it has to be inserted.. where IDs exist in #IdsToBeUpdated, updation would be done. For -1 values, insertion.
AS
BEGIN
BEGIN TRANSACTION
--------------------------Split input strings aand insert in Table variable----------------------------
declare #MCodes Table (pkey int primary key identity, MCode varchar(20))
insert into #MCodes select s.Item from [dbo].UDF_SplitString(#MCodeList, '|') s
declare #CusCodes Table (pkey int primary key identity, CusCode varchar(200))
insert into #CusCodes select s.Item from [dbo].UDF_SplitString(#CustomerIdsList, '|') s
declare #ReqDetailsIds Table (pkey int primary key identity, Id Int)
insert into #ReqDetailsIds select Convert(INT,RTRIM(LTRIM(s.Item))) from [dbo].UDF_SplitString(#IdsToBeUpdated, '|') s
where s.Item is not null and RTRIM(LTRIM(s.Item)) <>''
declare #ProductComments Table (pkey int primary key identity, Comment Varchar(max), insertedId int null)
insert into #ProductComments(Comment) select s.Item from [dbo].UDF_SplitString(#CommentList, '|') s
DECLARE #intErrorCode int;
------------------------------------------------------------------------------------------------------------
-----------------First Insertion which returns inserted IDs for 2nd insertion
------------------------------------------------------------------------------------------------------------------
---Insert/Update product details in [RequestDetails]
Declare #InsertedIDList Table (pkey int primary key identity, ID int); --------Table to read inserted Ids. Used in query below
-----------------------Insert query in case Detail id = -1
INSERT INTO [dbo].[RequestDetails]
[MCode]
,[CustomerIds]
,[ExpectedVolume]------Some parameters coming for first insertion in input
,[StatusCode])
Output INSERTED.ReqDetailId Into #InsertedIDList(ID)
SELECT A.MCode, B.CusCode, E.Vol,1
FROM #MCodes A
JOIN #CusCodes B ON B.pkey = A.pkey
JOIN #ExpectedVols E ON E.pkey = A.pkey
JOIN #ReqDetailsIds G ON G.pkey = A.pkey
WHERE G.Id = -1 --If id = -1, insert
---------------------------Update Query for rest records
UPDATE [dbo].[RequestDetails]
SET [MCode] = upd.MCode
,[CustomerIds] = upd.CusCode
,[ExpectedVolume] = upd.ExVol
,[StatusCode] = 1
FROM(
SELECT A.MCode, B.CusCode, E.ExVol, G.Id
FROM #MCodes A
JOIN #CusCodes B ON B.pkey = A.pkey
JOIN #ExpectedVols E ON E.pkey = A.pkey
JOIN #ReqDetailsIds G ON G.pkey = A.pkey
WHERE G.Id <> -1
) upd
WHERE upd.Id = dbo.RequestDetails.ReqDetailId
IF(##Error<>0)
BEGIN
SET #intErrorCode = ##Error
GOTO ERROR
END
ELSE
BEGIN
SET #ReturnValue=1
END
---------------------------------------------------------------------------
----------------------------Now similarly I have to do insert/update in Comments Table. But
----------------------------Comments table has RequestDetails Id column as foreign key. So
----------------------------now the challange is to add the rows with Inserted ID where value was = -1
----------------------------in input. We have got the IDs corresponding to -1 values from above insertion
----------------------------in the #InsertedIDList Table variable
-----------------------------------------------------------------------------------------
----------------------------Following is what I have tried so far. But I am not able to insert
----------------------------correct InsertedId against correct record.
----------------------------------------------------------------------------------------
-----------------------Here I tried to insert the new generated ids against corresponding comments in table variable.
-----------------------So that I can perform insert where value is not null. As NULL would be inserted where new ID has not been created
-----------------------and corresponding updated ID exists in input (Values not equal to -1)
-------------------------------------------------------------------------------------------------
Update #ProductComments set insertedId = i.ID from ---------This query is not working
(select A.pkey, B.id as detailId, row_number() over (order by (select 0)) as row_num from
#ProductComments A
JOIN #ReqDetailsIds B ON B.pkey = A.pkey) as mappedNewIds right join
#InsertedIDList i on i.pkey = mappedNewIds.row_num
where mappedNewIds.pkey = [#ProductComments].pkey
----Insert in CommentsTable for New Comments against request
---------------------------------
INSERT INTO [dbo].CommentsTable
( ReqDetailId, Comments, CreatedOn )
SELECT A.insertedId, A.Comment, GETDATE()
FROM #ProductComments A
where A.insertedId is not null
-----Update Query
------------------------------------------------------------------------------------------
UPDATE [dbo].[CommentsTable]
SET [ReqDetailId] = upd.Id
,[Comments] = upd.Comment
,[CreatedOn] = GetDate()
FROM(
SELECT A.Comment, B.Id
FROM #ProductComments A
JOIN #ReqDetailsIds B ON B.pkey = A.pkey
WHERE A.insertedId is not null
) upd
WHERE upd.Id = dbo.CommentsTable.ReqDetailId
END
select * from CommentsTable;
---------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
IF(##Error<>0)
BEGIN
SET #intErrorCode = ##Error
GOTO ERROR
END
ELSE
BEGIN
SET #ReturnValue=1
END
COMMIT TRANSACTION
ERROR:
IF (#intErrorCode <> 0) BEGIN
SET #ReturnValue = 0;
ROLLBACK TRANSACTION
END
END

Add Column To one table on inserting value to another table

I have two tables Branch_TB and Branch_City.
Branch_TB :
CREATE TABLE Branch_TB(
Branch_Id int NULL,
Branch_Name varchar(50) NULL
)
Whenever there is an entry for Branch_Name, I want to add that entry as column name in Branch_City.
Is there any way for this. I don't know how to do this and haven't try any solution.
Thanks in advance.
You can achieve that using AFTER INSERT TRIGGER.
CREATE TABLE Branch_TB(
Branch_Id int NULL,
Branch_Name varchar(50) NULL
)
go
--drop table BranchCity
create table BranchCity(abc varchar(20))
go
create TRIGGER dbo.AddCol
ON Branch_TB
AFTER INSERT AS
BEGIN
DECLARE #NewVal VARCHAR(20)
DECLARE #AlterSQL VARCHAR(100)
CREATE TABLE #New
(
VAL VARCHAR(20)
)
INSERT INTO #New
select Branch_Name from inserted
select #NewVal = Val from #New
SET #AlterSQL = 'ALTER TABLE BranchCity add ' + #NewVal + ' VARCHAR(20)'
exec(#AlterSQL)
END
go
insert into Branch_Tb
values(1, 'City1')
go
insert into Branch_Tb
values(2, 'City2')
But in my opinion, you should re-evaluate your database design.
you need to create trigger on insert row in Branch_TB table.
In trigger you need to add code for Add column in require table.
How to create Trigger in Sql ? check this.
I understand it like you want to duplicate inserted value in some other table in column name. If this is true then you can try with OUTPUT:
INSERT INTO Branch_TB( Branch_Id, Branch_Name )
OUTPUT 'someValue1', Inserted.Branch_Name, 'someValue2'
INTO Branch_City ( someCol1, Name, comeCol2 )
VALUES ( 1, 'some name' )
you can try this
create proc proc_branch (#b_name varchar(50)
as
begin
exec('alter table Branch_city add column '+ #b_name + ';');
end
go
create trigger tr_branch
on branch_TB
for insert
as
begin
declare #branch_name varchar(50);
set #branch_name=(select branch_name from inserted)
exec proc proc_branch
end

SQL Triggers - how do I get the updated value?

How do I get the value of the updated record in a SQL trigger - something like this:
CREATE TRIGGER TR_UpdateNew
ON Users
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
EXEC UpdateProfile (SELECT UserId FROM updated AS U);
END
GO
Obviously this doesn't work, but you can see what I am trying to get at.
Provide you are certain that only one value will ever be updated, you can do this...
CREATE TRIGGER TR_UpdateNew
ON Users
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
DECLARE #user_id INT
SELECT
#user_id = inserted.UserID
FROM
inserted
INNER JOIN
deleted
ON inserted.PrimaryKey = deleted.PrimaryKey
-- It's an update if the record is in BOTH inserted AND deleted
EXEC UpdateProfile #user_id;
END
GO
If multiple values can be updated at once, only one of them will get processed by this code. (Although it won't error.)
You could use a cursor, or if it's SQL Server 2008+ you can use table variables.
Or, more commonly, just move the StoredProcedure code into the trigger.
Based on my knowledge you would need to create a CURSOR to loop through all the updated values to execute the UpdateProfile procedure. Keep in mind this will slow down your update process.
Declare #UserID int --Assuming
Declare UpdateProfile_Cursor Cursor for Select UserID From inserted;
Open Cursor UpdateProfile_Cursor;
Fetch Next from UpdateProfile_Cursor Into #UserID;
While ##FETCH_STATUS == 0
Begin
Exec UpdateProfile #UserID
Fetch Next from UpdateProfile_Cursor Into #UserID;
End
CLOSE UpdateProfile_Cursor
DEALLOCATE UpdateProfile_Cursor
My syntax may be a little off but this will give you the desired effect. Again, consider revising your logic to handle multiple updates as using cursors is resource intensive.
You can do something like this example where I'm logging changes to a transaction history table:
create table dbo.action
(
id int not null primary key ,
description varchar(32) not null unique ,
)
go
insert dbo.action values( 1 , 'insert' )
insert dbo.action values( 2 , 'update' )
insert dbo.action values( 3 , 'delete' )
go
create table dbo.foo
(
id int not null identity(1,1) primary key ,
value varchar(200) not null unique ,
)
go
create table dbo.foo_history
(
id int not null ,
seq int not null identity(1,1) ,
action_date datetime not null default(current_timestamp) ,
action_id int not null foreign key references dbo.action ( id ),
old_value varchar(200) null ,
new_value varchar(200) null ,
primary key nonclustered ( id , seq ) ,
)
go
create trigger foo_update_01 on dbo.foo for insert, update , delete
as
set nocount on
set xact_abort on
set ansi_nulls on
set concat_null_yields_null on
--
-- record change history
--
insert dbo.foo_history
(
id ,
action_id ,
old_value ,
new_value
)
select id = coalesce( i.id , d.id ) ,
action_id = case
when i.id is not null and d.id is null then 1 -- insert
when i.id is not null and d.id is not null then 2 -- update
when i.id is null and d.id is not null then 3 -- delete
end ,
old_value = d.value ,
new_value = i.value
from inserted i
full join deleted d on d.id = i.id
go
But you can use the same sort of technique, mix it up a bit and pass the entire set of values to a stored procedure, like I do in the following example (using the table schema above).
First, create a stored procedure that expects a particular temp table to exist at runtime, thus:
--
-- temp table must exist or the stored procedure won't compile
--
create table #foo_changes
(
id int not null primary key clustered ,
action_id int not null ,
old_value varchar(200) null ,
new_value varchar(200) null ,
)
go
--
-- create the stored procedure
--
create procedure dbo.foo_changed
as
--
-- do something useful involving the contents of #foo_changes here
--
select * from #foo_changes
return 0
go
--
-- drop the temp table
--
drop table #foo_changes
go
Once you've done that, create a trigger that will create and populate the temp table expected by the stored procedure and then execute the stored procedure:
create trigger foo_trigger_01 on dbo.foo for insert, update , delete
as
set nocount on
set xact_abort on
set ansi_nulls on
set concat_null_yields_null on
--
-- create the temp table. This temp table will be in scope for any stored
-- procedure executed by this trigger. It will be automagickally dropped
-- when trigger execution is complete.
--
-- Any changes made to this table by a stored procedure — inserts,
-- deletes or updates are, of course, visible to the trigger upon return
-- from the stored procedure.
--
create table #foo_changes
(
id int not null primary key clustered ,
action_id int not null ,
old_value varchar(200) null ,
new_value varchar(200) null ,
)
--
-- populate the temp table
--
insert #foo_changes
(
id ,
action_id ,
old_value ,
new_value
)
select id = coalesce( i.id , d.id ) ,
action_id = case
when i.id is not null and d.id is null then 1 -- insert
when i.id is not null and d.id is not null then 2 -- update
when i.id is null and d.id is not null then 3 -- delete
end ,
old_value = d.value ,
new_value = i.value
from inserted i
full join deleted d on d.id = i.id
--
-- execute the stored procedure. The temp table created above is in scope
-- for the stored procedure, so it's able to access the set of changes from
-- the trigger.
--
exec dbo.foo_changed
go
That's about all there is to it. It's simple, it's easy, it works for change sets of any size. And, it's safe, with no race conditions or collisions with other users in the system.