please help me out for this query - sql-server

i given the countryId and countrname as 33 and india if i give the same countryid and countryname it has to give the message as updated. please tell me the code for that.. I wrote like this
IF EXISTS (SELECT * FROM Table1 WHERE CountryName=#CountryName )
BEGIN
SELECT 'already exists'
END
ELSE BEGIN
UPDATE Table1
SET
CountryName = #CountryName
WHERE CountryId = #CountryId
SELECT #QStatus = 'values updated';
END

Your IF statement logic is not correct. UPDATE is used to change existing rows, so if the row does not exist there is nothing to UPDATE.
You need to use INSERT
IF EXISTS (SELECT * FROM Table1 WHERE CountryName=#CountryName )
BEGIN
SELECT 'already exists'
END
ELSE BEGIN
INSERT Table1 (CountryName, CountryId)
VALUES (#CountryName, CountryId)
SELECT #QStatus = 'values inserted';
END
However, if what you need to do is replace the country name of the ID passed in you can use
IF EXISTS (SELECT * FROM Table1 WHERE CountryId=#CountryId )
BEGIN
UPDATE Table1
SET
CountryName = #CountryName
WHERE CountryId = #CountryId
SELECT #QStatus = 'values updated';
END
From the SQL you have provided it's hard to tell what you are actually trying to do.

Related

SQL Server: Cannot retrieve value from temp table with where statement

I have the following stored procedure, it inserts a record into Table2, and updates id column in Table1. The id in Table1 comes from the serial key in Table2.
I used SCOPE_IDENTITY() to get the latest assigned serial key in the scope.
However, when I execute the procedure and #flag = 1, no record is selected.
I know WHERE id = #id is something wrong because when I comment out the where clause, it works.
DECLARE #id INT
SELECT id, * INTO #t FROM Table1
IF #flag = 1
BEGIN
INSERT INTO Table2 (col1, col2)
VALUES ('value', 'value2')
SET #id = SCOPE_IDENTITY()
UPDATE Table1
SET id = #id
SELECT *
FROM #t
WHERE id = #id ---this is the problem!!
END
ELSE
BEGIN
SELECT * FROM #t
END
What is wrong with this?
Here's the issue, your IDs are not yet available in your #t table. Populate this table after you update your ID in Table1.
BEGIN
DECLARE #id INT
IF #flag = 1
BEGIN
Insert Table2(col1,col2)
VALUES ('value', 'value2')
SET #id = SCOPE_IDENTITY();
UPDATE Table1
SET id = #id;
SELECT id, * INTO #t From Table1; -- This should be its position.
SELECT *
FROM #t
WHERE id = #id
END
ELSE
BEGIN
SELECT id, * FROM Table1
END
END

How to read uncommitted data from other table inside trigger

I have 2 tables, Contact and ContactFunction. They have a One to Many relationship, as in a Contact can have many ContactFunctions. So ContactFunction has ContactID as a foreign key. So in my .NetCore web application I can update a contact and their functions on the same page. But this is in fact saving two separate entities, named above. I have a trigger on the Contact table that puts inserts/updates/deletes into a history table. I need a way to also include any ContactFunction changes in this trigger too. But at this stage it seems there has been no commits yet to the ContactFunction table, because of the relationship I assume. Can you think of a way to do this other than creating a history table for both?
I'm trying to read the data from the ContactFunction table inside the Contact table trigger, but it's not there yet. the variable #FUNCTIONSSTRING is where I'm trying to read data from the second table (ContactFunction)
USE [DI_Business_IE_EF_Development04]
GO
/****** Object: Trigger [dbo].[ContactHistoryLog] Script Date: 25/01/2019 09:33:00 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TRIGGER [dbo].[ContactHistoryLog] ON [dbo].[Contact]
AFTER INSERT,UPDATE, DELETE
AS
BEGIN
SET NOCOUNT ON;
DECLARE #CurrentDateTime datetime2 = SYSUTCDATETIME();
DECLARE #Action varchar(10);
DECLARE #CONTACTID INT;
DECLARE #FIRSTUPDATE INT;
DECLARE #FUNCTIONSSTRING VARCHAR(250) = '';
DECLARE #INSERTEDID INT;
IF EXISTS (SELECT 1 FROM inserted)
BEGIN
IF EXISTS (SELECT 1 FROM deleted)
BEGIN
SET #Action = 'UPDATE'
END
ELSE
BEGIN
SET #Action = 'INSERT'
END
END
ELSE
BEGIN
SET #Action = 'DELETE'
END
/* Update start times for newly updated data */
UPDATE c
SET
StartDate = #CurrentDateTime, #CONTACTID = c.ID
FROM
dbo.Contact c
INNER JOIN inserted i
ON c.Id = i.Id
SELECT #FIRSTUPDATE = COUNT(*) FROM dbo.ContactHistory WHERE ContactId = #CONTACTID
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
SELECT
#FUNCTIONSSTRING = #FUNCTIONSSTRING + F.Name + ','
FROM ContactFunction CF
JOIN [Function] F ON F.ID = CF.FunctionID
WHERE CF.ContactID = #CONTACTID
INSERT INTO DBO.ContactHistory(
ContactId,
CompanyID,
Title,
Forename,
Surname,
JobTitle,
ExecutiveNumber,
IsInformationProvider,
Email,
UpdatedBy,
StartDate,
EndDate,
[Action],
FunctionNames
)
SELECT
I.Id,
I.CompanyID,
I.Title,
I.Forename,
I.Surname,
I.JobTitle,
I.ExecutiveNumber,
I.IsInformationProvider,
I.Email,
I.UpdatedBy,
#CurrentDateTime,
#CurrentDateTime,
#Action,
(SELECT SUBSTRING(#FUNCTIONSSTRING, 0, LEN(#FUNCTIONSSTRING)))AS FunctionNames
FROM
dbo.Contact c
RIGHT JOIN inserted I
ON c.Id = I.Id
-- if this is first update insert deleted value as well as inserted value, else just put in inserted
IF (#FIRSTUPDATE = 0)
BEGIN
INSERT INTO DBO.ContactHistory(
ContactId,
CompanyID,
Title,
Forename,
Surname,
JobTitle,
ExecutiveNumber,
IsInformationProvider,
Email,
UpdatedBy,
StartDate,
EndDate,
[Action],
FunctionNames
)
SELECT
d.Id,
d.CompanyID,
d.Title,
d.Forename,
d.Surname,
d.JobTitle,
d.ExecutiveNumber,
d.IsInformationProvider,
d.Email,
d.UpdatedBy,
d.StartDate,
ISNULL(d.StartDate,#CurrentDateTime),
'NONE',
(SELECT SUBSTRING(#FUNCTIONSSTRING, 0, LEN(#FUNCTIONSSTRING)))AS FunctionNames
FROM
dbo.Contact c
RIGHT JOIN deleted d
ON c.Id = d.Id
END
END
I would expect to see the latest changes to the ContactFunction table, but it's not there. is there a way to do this?

Return table with different columns based on parameters SQL

I'm writing a stored procedure that runs different selects based on the user role , this is just an example to showcase my intention since i have a lot of roles to work with.
IF OBJECT_ID('dbo.spSelectArtigos') IS NOT NULL
DROP PROCEDURE spSelectArtigos
GO
CREATE PROCEDURE spSelectArtigos
#IdUser int,
#Acesso nvarchar(20)
AS
BEGIN
IF(#Acesso = 'User')
SELECT col1,col2 from table1 where IdUser = #IdUser
IF(#Acesso = 'Logistica')
SELECT col1,col2,col3 from table1 where IdUser = #IdUser
IF(#Acesso = 'Admin')
SELECT * From table1
END
Is there a more effective way to do this with less code using some sort of logic?
IDK why i added a check to make sure the user actually exists but it isnt a bad idea
IF OBJECT_ID('dbo.spSelectArtigos') IS NOT NULL
DROP PROCEDURE spSelectArtigos
GO
CREATE PROCEDURE spSelectArtigos
#IdUser int,
#Acesso nvarchar(20)
AS
BEGIN
CASE
WHEN #Acesso ='User'
AND
EXISTS (SELECT * FROM table1 WHERE IdUser = #IdUser)
THEN
SELECT col1,col2 from table1 where IdUser = #IdUser
WHEN #Acesso ='Logistica' Then
AND
EXISTS (SELECT * FROM table1 WHERE IdUser = #IdUser)
THEN
SELECT col1,col2,col3 from table1 where IdUser = #IdUser
WHEN #Acesso ='Admin'
AND
EXISTS (SELECT * FROM table1 WHERE IdUser = #IdUser)
THEN
SELECT * From table1
END
END
Here is a kludgy way but it is concise.
IF OBJECT_ID('dbo.spSelectArtigos') IS NOT NULL
DROP PROCEDURE spSelectArtigos
GO
CREATE PROCEDURE spSelectArtigos
#IdUser int,
#Acesso nvarchar(20)
AS
BEGIN
DECLARE #Result TABLE(A INT,B INT,C INT,D INT)
INSERT #Result SELECT A,B,C,D FROM table1 WHERE idUser=#idUser
IF(#Acesso = 'User')
UPDATE #Result SET C=NULL, D=NULL
IF(#Acesso = 'Logistica')
UPDATE #Result SET D=NULL
SELECT * From #Result
END
Another way but dealing with ID's
SELECT
A=CASE WHEN #Acesso >= 10 THEN A ELSE NULL END,
B=CASE WHEN #Acesso >= 20 THEN B ELSE NULL END,
C=CASE WHEN #Acesso >= 99 THEN C ELSE NULL END
FROM
table1
WHERE
idUser=#idUser

SQL Server- Trigger. Update a column on one table with a count of columns from another table

Trying to learn triggers and can't seem to wrap my head around whether this is the best way to go about this. There is a total of 'tickets' that I would like to count and put into a column for an 'order'.
CREATE TRIGGER DAILYTICKETTOTALS
ON db.ORDER
AFTER UPDATE
AS
BEGIN
INSERT INTO db.ORDER (
--Finding the order they made for the day:
SELECT * FROM db.ORDER
WHERE DESCRIPTION = 'specific description' AND
CAST(CAST(CAST(GETDATE()AS float) AS int) AS datetime) =
CAST(CAST(CAST(db.ORDER.STARTDATE AS float) AS int) AS datetime)
AND db.ORDER.CREATEDBY = 'Last, First'
)
SET db.ORDER.COLUMNTOTALS VALUES(
--Finding the total of tickets input for the day
SELECT COUNT(*)
FROM db.ticket
WHERE CAST(CAST(CAST(db.ticket.DATE AS float) AS int) AS datetime) =
CAST(CAST(CAST(GETDATE()AS float) AS int) AS datetime)
AND db.ticket.INPUTBY = 'Last, First');
Thanks for any help, and I appreciate you reviewing this.
Do some research on the "Special" tables available inside a trigger, such as "INSERTED" as that will give you the details of the rows that have been updated, and you can join that to anything else (including the actual table being updated) that you need to. Remember that you should not assume there is only 1 row updated, as the trigger will fire once per batch, not once per row.
This is a version of your stored proc that assumes that each order has a unique ID named OrderID, and that both the ticket and order table have a personID rather than looking for them by name. If not, they should, and if you cant change it then use your existing messy joins.
CREATE TRIGGER DAILYTICKETTOTALS
ON db.ORDER
AFTER UPDATE
AS
BEGIN
update o
set columntotals=TicketNum
from inserted
join db.[order] o on o.orderid=inserted.orderid
join (
select convert(date,ticket,[date]) as ticketdate, PersonID, count(*) as TicketNum
from db.ticket
group by convert(date,ticket,[date]) as ticketdate, PersonID
) t on t.PersonID=o.PersonID and t.ticketdate=convert(date,getdate())
This solved my problem, in case any of you were curious. I don't know if its ideal, but it works.
CREATE TRIGGER DAILYTICKETTOTALS
ON db.ORDER
AFTER INSERT, UPDATE
AS
BEGIN
DECLARE #INS NVARCHAR(50)
SELECT #INS = NAMECOLUMN FROM INSERTED
WHERE DESCRIPTION = 'specific description' AND
CAST(CAST(CAST(STARTDATE AS float) AS int) AS datetime)=
CAST(CAST(CAST(GETDATE() AS float) AS int) AS datetime)
END
IF #INS = ‘Last, First’
BEGIN
UPDATE db.ORDER
SET COLUMNTOTALS = EXAMPLENAME.CT
FROM (SELECT COUNT(*) AS CT FROM ticket WHERE INPUTBY = ‘Last, First’) EXAMPLENAME
WHERE DESCRIPTION = 'specific description' AND INPUTBY = ‘Last, First’
END
BEGIN

Check for duplicate record before insert in SQL Server 2005

In sql server 2005 I have a table like this
empno name project
-------- -------- -----------
1 ram pro-1
2 sheik pro-2
Now I want to raise error when I try to insert record with empno and project values already present in table.
If exists then RAISERROR unless insert accordingly, code block is given below:
IF EXISTS (SELECT 1 FROM targetTable AS t
WHERE t.empNo = #yourEmpNo
AND t.project = #yourProject)
BEGIN
RAISERROR('Raising errors',18,1)
END
ELSE
BEGIN
INSERT INTO yourTable (empno, name, project)
SELECT #empno, #name, #project
END
If you want to raise an error, you could put a UNIQUE INDEX or UNIQUE CONSTRAINT on (empno, project) When you try to INSERT a value that conflicts with the INDEX/CONSTRAINT an exception will be thrown.
Alternatively you can insert if the record doesn't exist or update name if it is already in the table:
IF NOT EXISTS (SELECT 1
FROM yourTable AS t
WHERE t.empNo = #yourEmpNo
AND t.project = #yourProject)
BEGIN
INSERT INTO yourTable (empno, name, project)
SELECT #empno, #name, #project
END
ELSE
BEGIN
UPDATE t
SET t.Name = #name
FROM yourTable AS t
WHERE t.empno = #empno
AND t.project = #project
END

Resources