Procedure that store updated history of table in another table - mysql

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

Related

SQL - Procedure function

Trying to create a Procedure to (Insert, Delete and, Update) values in employee_details.
CREATE DEFINER=`root`#`localhost` ALTER PROCEDURE `alter_employeedetails`(in employee_id int(11), employee_name VARCHAR(30), employee_join_date date,
employee_desgination varchar(30), employee_salary bigint(20), employee_address varchar(30),
employee_contact varchar(30), employee_email_id varchar(30)
BEGIN
IF #StatementType = 'Insert'
BEGIN
insert into employee_details values
(employee_id, employee_name, employee_join_date, employee_desgination, employee_salary, employee_address, employee_contact, employee_email_id)
END
IF #StatementType = 'Update'
BEGIN
UPDATE employee_details SET
(employee_name = #employee_name, employee_join_date = #employee_join_date, employee_designation = #employee_desgination,
employee_salary = #employee_salary, employee_address = #employee_address, employee_contact = #employee_contact, employee_email_id = #employee_email_id)
WHERE employee_id = #employee_id
END
else IF #StatementType = 'Delete'
BEGIN
DELETE FROM employee_details where employee_id = #employee_id
END
end
Quite a few errors in that code...
You forgot to prefix all the parameters with the "#" symbol.
Forgot to include "#StatementType" as a parameter.
Update had brackets around it.
You cannot specify int(11) (employee_id) or bigint(20)
(salary). It's either int / bigint (you don't specify the length
for int/bigint datatypes). And is salary correct as bigint? MSSQL has a "money"
datatype, or you could use decimal(8,2) or something similar. You
might be multiplying the salary by 100 to shift the decimal place for
all I know?
When inserting, do you really want to insert a employee Id? This would normally be an auto-incrementing primary key
Insert statement missing the fields you were populating. Required if using the "values" keyword like you had specified.
Hopefully this is closer to what you want.
ALTER PROCEDURE alter_employeedetails
(#StatementType as varchar(25), #employee_id int, #employee_name VARCHAR(30), #employee_join_date date,
#employee_designation varchar(30), #employee_salary bigint, #employee_address varchar(30),
#employee_contact varchar(30), #employee_email_id varchar(30))
AS
BEGIN
IF #StatementType = 'Insert'
BEGIN
insert into employee_details
(employee_id, employee_name, employee_join_date, employee_designation, employee_salary, employee_address, employee_contact, employee_email_id)
values
(#employee_id, #employee_name, #employee_join_date, #employee_designation, #employee_salary, #employee_address, #employee_contact, #employee_email_id)
END
ELSE IF #StatementType = 'Update'
BEGIN
UPDATE employee_details
SET
employee_name = #employee_name,
employee_join_date = #employee_join_date,
employee_designation = #employee_designation,
employee_salary = #employee_salary,
employee_address = #employee_address,
employee_contact = #employee_contact,
employee_email_id = #employee_email_id
WHERE employee_id = #employee_id
END
ELSE IF #StatementType = 'Delete'
BEGIN
DELETE FROM employee_details where employee_id = #employee_id
END
END

Insert into Table Variable getting Column name or number of supplied values does not match table definition

DECLARE #myTemp TABLE (Item Varchar(10) Not Null,
[Description Varchar(30) Not Null,
LonDescription Varchar(50),
[Level] Char(1),
LevelDesc Varchar(15),
GID Varchar(16),
[Min] Int,
[Max] Int,
QTY Int,
QoO Int)
FETCH NEXT FROM cAreaLocationItems Into #citem,#cDesc,#cLDesc,#cLVL,#cLVLDesc,#cGID,#cMin,#cMax,#cqty
IF ##FETCH_STATUS <> 0 -- We're out of items
BREAK
WHILE ##FETCH_STATUS = 0
Begin
Declare #QoO Int
SELECT #QoO = SUM(QtyReqd - QtyActual)
FROM abc.tblorders
WHERE (ItemNumber = #cItem) AND (Status <> '4') And
Bin = #Location
GROUP BY ItemNumber, UPC, [Level], Description, Bin
If #QoO = Null
Set #QoO = 0
Insert into #myTemp values(#cItem,#cDesc,#cLDesc,#clvl,#cLVLDesc,#cGid,#cMin,#cMax,#cQTy,#QoO)
FETCH NEXT FROM cAreaLocationItems Into #citem,#cDesc,#cLDesc,#cLVL,#cLVLDesc,#cGID,#cMin,#cMax,#cqty
end
Get the error executed stored procedure on the insert into #myTemp table variable defined above. Table says 10 columns and insert has ten values. Any help?
Try to specify the column names in the insert query like this:
Insert into #myTemp (Item Varchar,[Description,LonDescription,Level],LevelDesc,GID,[Min],[Max],QTY,QoO) values(#cItem,#cDesc,#cLDesc,#clvl,#cLVLDesc,#cGid,#cMin,#cMax,#cQTy,#QoO)
It helps you to avoid error when you add new column into the table

Join two table and then search for the match

I have two table named security_questions and login. Columns in login tables are:
Username, Security_QA_ID, Security_Answer, Security_Attempts,Last_Login,Password_Attempts
where security_questions have:
ID, Name
where Security_QA_ID is referenced with ID
CREATE DEFINER=`satish`#`%` PROCEDURE `p_chkAnswer`(
IN sq VARCHAR(75),
IN sa VARCHAR(20) ,
IN uname VARCHAR(15) ,
out msg INT
)
BEGIN
select (COUNT(*) > 0) INTO #result from login join security_questions on Security_QA_ID = ID where User_Name=uname and Name=sq and Security_Answer=sa;
set msg = #result;
if #result = 1 Then
UPDATE login SET Last_Login=now(),Password_Attempts=0 where User_Name=uname;
else
UPDATE login SET Security_Attempts=Security_Attempts+1 where User_Name=uname;
End if;
END
but in every time only else part get executes. thanks in advance
Your code is quite confusing and hard to read (for me at least), I simplified your statement into a single SELECT so that I can check if your select is correct, and it appears to be correct:
CREATE TABLE `login`
( User_Name text,
Security_QA_ID int(11),
Security_Answer text,
Security_Attempts datetime,
Last_Login datetime,
Password_Attempts int(11)
);
CREATE TABLE `security_questions`
(ID int(11),
Name text
);
INSERT INTO login SET
User_name = 'a',
Security_QA_ID = 1,
Security_Answer = 'c',
Security_Attempts = NOW(),
Last_Login = NOW(),
Password_Attempts = 0;
INSERT INTO security_questions SET
ID = 1,
Name = 'b';
And the select
SELECT IF(COUNT(*) > 0, 1, 0) AS Authenticated
from (login)
LEFT join security_questions on Security_QA_ID = ID
where User_Name='a' and Name='b' and Security_Answer='c'
Do you have to use this DEFINER? wouldn't it be easier to write PHP/Perl/etc code to check for Authenticated as being non-zero?

SQL - If statement seemingly ignoring 'AND'

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!'

Loop through a table and assign foreign key to new record if null

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