I made the following stored procedure which will be called when creating a new employee.
The insert should be successful so long as the employee doesnt already exist in the Employee table.
To check for this I decided to check FirstName, LastName and DateOfBirth. If a row contains a 3 way match of all those columns, the insert should fail.
What i'm seeing is that the If statement is treating my AND as an OR.
If one match occurs the insert fails.
After some searching around I cant see to see what is wrong with my If structure.
Any help would be appreciated.
Create Procedure CreateEmployee
(
#Role_ID Int,
#FirstName Varchar(50),
#LastName Varchar(50),
#DateOfBirth Varchar(50),
#Active Bit
)
As
Begin
If Not Exists (Select FirstName From Employee Where FirstName = #FirstName)
AND Not Exists (Select LastName From Employee Where LastName = #LastName)
AND Not Exists (Select DateOfBirth From Employee Where DateOfBirth = #DateOfBirth)
Begin
Insert Into Employee (Role_ID, FirstName, LastName, DateOfBirth, Active)
Values (#Role_ID, #FirstName, #LastName, #DateOfBirth, #Active)
End
Else
Begin
Select 'User already exists!'
End
End
Why are you not just running 1 query for your check?
If Not Exists (Select 1 From Employee
Where FirstName = #FirstName
and LastName = #LastName
and DateOfBirth = #DateOfBirth)
begin
...
This is another way (##rowcount for sql server): using Where not exists. Similar Sql Fiddle Demo
Insert Into Employee (Role_ID, FirstName, LastName, DateOfBirth, Active)
Select #Role_ID, #FirstName, #LastName, #DateOfBirth, #Active
Where not exists (
select 1 from Employee where FirstName = #FirstName
and LastName = #LastName
and DateOfBirth = #DateOfBirth
)
If ##rowcount=0 select 'User already exists!'
Related
I need to validate if a record already exists. The portion, in the stored procedure, that does that is:
SELECT EXISTS (SELECT 1 FROM MyTable
WHERE FirstName = #FirstName
AND LastName = #LastName
AND Address = #Address)
BEGIN
SET #IsNewRecord = 1
END
IF #IsNewRecord = 1
BEGIN
INSERT INTO MyTable
VALUES (#FirtName, #LastName, #Addres, #City, #Phone)
END
That works fine, the issue is when the stored procedure is called by several clients at the same time, it will return the #IsNewRecord = 1.
I already tried surrounding the validation among a TRANSACTION BLOCK, but it still creates a new record.
How can I handle concurrency when using SELECT?
do like this
begin transaction
SELECT EXISTS (SELECT 1 FROM MyTable WHERE FirstName = #FirstName AND LastName = #LastName
AND Address = #Address)
BEGIN
INSERT INTO MyTable
VALUES (#FirtName, #LastName, #Addres, #City, #Phone)
END
commit
I have two tables Person with PersonId, Name,Address,Mobile and PersonLog with Id,Name,Address,Mobile,FK_PersonId. I am trying store the old data in PersonLog and Person to be updated.
This is my procedure, but it is only updating Person and not storing selected(edited) data from Person into PersonLog :
CREATE PROCEDURE [dbo].[UpdateInsertPerson]
(
#PersonId int,
#PersonName nvarchar(40),
#Address nvarchar(60),
#Mobile nvarchar(15)
)
AS
BEGIN
INSERT INTO
dbo.PersonLog(PersonName, Address, Mobile, FK_PersonId)
SELECT
Person.PersonId, Person.PersonName, Person.Address, Person.Mobile
FROM
dbo.Person JOIN dbo.PersonLog ON PersonLog.FK_PersonId = Person.PersonId;
UPDATE
dbo.Person
SET
PersonName = #PersonName,
Address = #Address,
Mobile = #Mobile
WHERE
PersonId = #PersonID;
END
Any help?
I might suggest these changes... but I don't know what you're after exactly. Or your data.
I highly suggest adding a modified date to your PersonLog table....
alter table PersonLog add Modified_DT datetime default getdate()
this code works for me...
CREATE PROCEDURE UpdateInsertPerson (
#PersonId int,
#PersonName nvarchar(40) = null,
#Address nvarchar(60) = null,
#Mobile nvarchar(15) = null
)
AS
BEGIN
INSERT INTO PersonLog (FK_PersonId, PersonName, Address, Mobile)
SELECT Person.PersonID,
Person.PersonName,
Person.Address,
Person.Mobile
FROM Person
WHERE Person.PersonId=#PersonID;
UPDATE Person
SET PersonName = case when #PersonName is not null then #PersonName else PersonName end,
Address = case when #Address is not null then #Address else Address end,
Mobile = case when #Mobile is not null then #Mobile else Mobile end
WHERE PersonId = #PersonID;
END
insert into Person values (1,'kim','123 main st','555-555-5555');
exec UpdateInsertPerson 1,'kim';
exec UpdateInsertPerson 1,'ryan';
exec UpdateInsertPerson 1,'taco';
select * from personlog
select * from Person
that way will not insert a brand new person. this way will... for this to work, your Person.PersonID must be set like this: PersonID int IDENTITY(1,1) primary key.
ALTER PROCEDURE UpdateInsertPerson (
#PersonId int = null,
#PersonName nvarchar(40) = null,
#Address nvarchar(60) = null,
#Mobile nvarchar(15) = null
)
AS
BEGIN
INSERT INTO PersonLog (FK_PersonId, PersonName, Address, Mobile)
SELECT Person.PersonID,
Person.PersonName,
Person.Address,
Person.Mobile
FROM Person
WHERE Person.PersonId=#PersonID;
UPDATE Person
SET PersonName = case when #PersonName is not null then #PersonName else PersonName end,
Address = case when #Address is not null then #Address else Address end,
Mobile = case when #Mobile is not null then #Mobile else Mobile end
WHERE PersonId = #PersonID;
-- this inserts into Person if they didn't already exist
IF ##ROWCOUNT = 0
BEGIN
INSERT Person (PersonName, Address, Mobile) VALUES (#PersonName, #Address, #Mobile);
END
END
The procedure is not working as you are joining PersonLog with Person table in the select statement. As initially this table is empty the condition PersonLog.FK_PersonId = Person.PersonId is false and nothing gets inserted (as FK_PersonId is NULL)
I don't see any purpose of joining the 2 tables to insert the record in Log table. just remove the join condition and include a where clause as Person.PersonId=#PersonID
Can anyone tell me what is wrong with the following procedure? MySQL says it is an 'unexpected IF'. I looked up the syntax for an IF statement and I simply don't see what the problem is.
create procedure spInsertAccount
(
AccountID INT,
InUse bit,
IsBanned bit,
IsPremium bit,
IsGolden bit,
Username VARCHAR(20),
Password VARCHAR(20),
Email VARCHAR(65),
LoggedInID INT,
CreateDate DATETIME
)
SET #accountExists = (SELECT * FROM Accounts WHERE AccountID = #AccountID);
IF (accountExists > 0) THEN
INSERT IGNORE INTO Accounts(AccountID, InUse, IsBanned, IsPremium, IsGolden, Username, Password,
Email, LoggedInID, CreateDate
)
values (#AccountID, #InUse, #IsBanned, #IsPremium, #IsGolden, #Username, #Password,
#Email, #LoggedInID, #CreateDate);
#where NOT EXISTS( SELECT * FROM Accounts WHERE AccountID = #AccountID);
END IF;
Try this instead
Also check out here http://net.tutsplus.com/tutorials/an-introduction-to-stored-procedures/
DELIMITER //
create procedure `spInsertAccount`
(
IN AccountID INT,
IN InUse bit,
IN IsBanned bit,
IN IsPremium bit,
IN IsGolden bit,
IN Username VARCHAR(20),
IN Password VARCHAR(20),
IN Email VARCHAR(65),
IN LoggedInID INT,
IN CreateDate DATETIME
)
BEGIN
SET #accountExists = (SELECT * FROM Accounts WHERE AccountID = #AccountID);
if (accountExists > 0) THEN
INSERT IGNORE INTO Accounts(AccountID, InUse, IsBanned, IsPremium, IsGolden, Username, Password,Email, LoggedInID, CreateDate)
values (#AccountID, #InUse, #IsBanned, #IsPremium, #IsGolden, #Username, #Password,
#Email, #LoggedInID, #CreateDate);
#where NOT EXISTS( SELECT * FROM Accounts WHERE AccountID = #AccountID);
END IF;
END //
I have 3 tables-
1. Country (CountryName, CID (PK- AutoIncrement))
2. State (SID(PK- AutoIncrement), StateName, CID (FK to Country)
3. City (CityName, CID, SID (FK to State)
Now I need to insert only the name into the three tables with CountryName, StateName and CityName.. The IDs need to get updated.
Create PROCEDURE sp_place(
#CountryName char(50),
#StateName varchar(50),
#CityName nchar(20)
)
AS
DECLARE #CountryID int, #StateID int, #CityID int;
Set NOCOUNT OFF
BEGIN TRANSACTION
INSERT INTO dbo.Country VALUES (#CountryName);
SET #CountryID = SCOPE_IDENTITY();
IF ##ERROR <> 0
BEGIN
ROLLBACK
RETURN
END
Insert into dbo.State VALUES (#StateName, #CountryID);
SET #StateID = SCOPE_IDENTITY();
IF ##ERROR <> 0
BEGIN
ROLLBACK
RETURN
END
Insert into dbo.City VALUES (#CityName, #StateID);
SET #CityID= SCOPE_IDENTITY();
Commit
When I Enter Country twice, the value shouldn't get changed.
Eg: If I enter India the value of CountryID=1, when I again enter India, the value of CountryID shouldn't get increased.
How'd I perform that? My SP changes for every insertion.
You can check if the country already exist and retrieve the countryID
IF NOT EXISTS(Select 1 FROM Country Where CountryName=#Country)
BEGIN
INSERT INTO dbo.Country VALUES (#CountryName);
SET #CountryID = SCOPE_IDENTITY();
END
ELSE
Select #CountryID = CountryID From Country Where CountryName=#Country
You can do the same for State and City if required
Hello try with this syntax
IF EXISTS (SELECT * FROM Country WHERE CountryName= #CountryName)
BEGIN
UPDATE dbo.Country
SET CountryName = #CountryName
WHERE CountryId = (SELECT CountryId FROM dbo.Country WHERE CountryName= #CountryName);
END
ELSE
BEGIN
INSERT INTO dbo.Country(CountryName) VALUES (#CountryName);
END
-- For the identity you must just add identity to your column in your creation script
Why dont you set Unique Constraint on CountryName column that won't allow you to insert duplicate countries at all
You need the MERGE syntax
http://technet.microsoft.com/en-us/library/bb510625.aspx
or to check manually (ie: with IF EXISTS (...) ) for the existence of the country before inserting.
I am working on an SQL Database
I have a Table Users
Id Name Age AddressId
----+------+------+-----------
Where AddressId is a foreign key to a table names Addresses
The Addresses Table:
Id Country State City ZipCode
----+---------+------+------+---------
I need an SQL Script, that loops through all the users and If the AddressId of that user is null, Create a new record in the Addresses Table with default Values and assign it to the user as a foreign key
Something like this in SQL script:
Foreach (User in Users)
If(user.AddressId==null)
INSERT INTO Addresses values('DefaultCountry', 'DefaultState', 'DefaultCity', 99999)
User.AddressId= the id of the newly created row
EDIT
It is a one-to-one relationship
thanks for any help
You can use merge and output to do this without a loop.
declare #IDs table(UserId int, AddressId int);
merge Addresses as T
using (select Id, 'DefaultCountry', 'DefaultState', 'DefaultCity', 99999
from Users
where AddressID is null) as S (UserId, Country, State, City, ZipCode)
on 0 = 1
when not matched then
insert(Country, State, City, ZipCode)
values (S.Country, S.State, S.City, S.ZipCode)
output S.UserId, inserted.Id into #IDs;
update Users
set AddressId = IDs.AddressID
from #IDs as IDs
where Users.Id = IDs.UserId;
SE-Data
If you only need to add one address and connect that one to all users that have none use this instead.
declare #AddressId int;
insert into Addresses(Country, State, City, ZipCode)
values('DefaultCountry', 'DefaultState', 'DefaultCity', 99999);
set #AddressId = scope_identity();
update Users
set AddressId = #AddressId
where AddressId is null;
create table #Users
(
id int,
AddressID int
)
insert into #Users(id, AddressID)values(1, 1)
insert into #Users(id, AddressID)values(2, null)
create table #Address
(
id int Identity(1,1),
nam varchar(100)
)
declare #id int
declare #AddressID int
declare #NewAddressID int
declare cur cursor for Select id, AddressID from #Users Where AddressID is null
open cur
Fetch next from cur into #id, #AddressID
While(##Fetch_Status = 0)
Begin
Fetch next from cur into #id, #AddressID
insert into #Address(nam)values(NEWID())
Set #NewAddressID = SCOPE_IDENTITY();
Update #Users
Set AddressID = #NewAddressID
Where id = #id
End
Deallocate cur
SELECT * FROM #Address
SELECT * FROM #Users
drop table #Address
drop table #Users