I'm trying to implement a stored procedure like this where it's going to compare UserID from another table. If that user id already exists in dbo.user info table, it will insert data into [dbo].[BulkUploadTagDetail] table.
Every time I execute this stored procedure running into an issue that the data doesn't get inserted into my database table.
CREATE PROCEDURE [dbo].[InsertBulkUploadTagDetail]
(#BulkTagID INT,
#PortalUserID UNIQUEIDENTIFIER,
#EmailAddress VARCHAR(256),
#BulkUploadFileName VARCHAR(256),
#CreatedOn DATETIME2(7),
#IsCompleted BIT = 0)
AS
BEGIN
SET NOCOUNT ON
IF EXISTS (SELECT UserID
FROM dbo.UserInfo
WHERE UserID = #PortalUserID)
BEGIN
UPDATE [unp]
SET [unp].[BulkTagID] = #BulkTagID,
[unp].[UserID] = #PortalUserID,
[unp].[EmailAddress] = #EmailAddress,
[unp].[BulkUploadFileName] = #BulkUploadFileName,
[unp].[CreatedOn] = GETUTCDATE(),
[unp].[IsCompleted] = #IsCompleted
FROM
[dbo].[InsertBulkUploadTagDetail] unp
INNER JOIN
[dbo].[UserInfo] uinfo ON [unp].[UserID] = [uinfo].[UserID]
WHERE
[unp].[UserID] = #PortalUserID
END
ELSE
BEGIN
INSERT INTO [dbo].[BulkUploadTagDetail]
([BulkTagID], [PortalUserID], [EmailAddress],
[BulkUploadFileName], [CreatedOn], [IsCompleted])
VALUES (#BulkTagID, #PortalUserID, #EmailAddress,
#BulkUploadFileName, #CreatedOn, #IsCompleted)
END
END
Related
I have a Songs table with a likes column that holds the number of likes users sent . Each user sends a boolean (1 or 0) through a C# app which adds to the likes column.
About my procedure:
I want to know if there is more an efficient and short way of writing the part 1 of the function?
I had to manually insert '0' instead of the NULL for the first time for the function to work. It wasn't working because the initial value for Likes column is NULL. Is there a way to affect the row for the first time when it has NULL in it?
For part 2 of the function with [Users_Likes_Songs] table, I want to update if the user send a like (true = 1) or removed it (false = 0).
How can I update this table for the first time when the users 'like' must be valued as '1', when its rows are completely empty?
I thank you very much if you can help me.
The procedure:
CREATE PROCEDURE Songs_Likes
#User_ID INT,
#SongID INT,
#Song_like BIT
AS
BEGIN
--- part 1 of the function
IF (#Song_like = 1)
BEGIN
UPDATE [Songs]
SET [Likes] = [Likes] + #Song_like
WHERE [Song_ID] = #SongID
END
IF (#Song_like = 0)
BEGIN
UPDATE [Songs]
SET [Likes] = [Likes] - 1
WHERE [Song_ID] = #SongID
END
--- part 2 of the function with the second table
UPDATE [Users_Likes_Songs]
SET [LikeSong] = #Song_like
WHERE ([UserID] = #User_ID) AND ([SongID] = #SongID)
END
I think that the better method would be to change your design to calculate the likes and have a table that stores the likes for each user. In simple terms, something like:
USE Sandbox;
GO
CREATE SCHEMA music;
GO
CREATE TABLE music.song (SongID int IDENTITY(1,1),
Artist nvarchar(50) NOT NULL,
Title nvarchar(50) NOT NULL,
ReleaseDate date);
CREATE TABLE music.[User] (UserID int IDENTITY(1,1),
[Login] nvarchar(128));
CREATE TABLE music.SongLike (LikeID bigint IDENTITY(1,1),
SongID int,
UserID int,
Liked bit);
CREATE UNIQUE NONCLUSTERED INDEX UserLike ON music.SongLike(SongID, UserID); --Stops multiple likes
GO
--To add a LIKE you can then have a SP like:
CREATE PROC music.AddLike #SongID int, #UserID int, #Liked bit AS
BEGIN
IF EXISTS (SELECT 1 FROM music.SongLike WHERE UserID = #UserID AND SongID = #SongID) BEGIN
UPDATE music.SongLike
SET Liked = #Liked
WHERE UserID = #UserID
AND SongID = #SongID
END ELSE BEGIN
INSERT INTO music.SongLike (SongID,
UserID,
Liked)
VALUES (#SongID, #UserID, #Liked);
END
END
GO
--And, if you want the number of likes:
CREATE VIEW music.SongLikes AS
SELECT S.Artist,
S.Title,
S.ReleaseDate,
COUNT(CASE SL.Liked WHEN 1 THEN 1 END) AS Likes
FROM music.Song S
JOIN music.SongLike SL ON S.SongID = SL.SongID
GROUP BY S.Artist,
S.Title,
S.ReleaseDate;
GO
For 1) this is a bit clearer, shorter and a bit more efficient.
UPDATE [Songs]
SET [Likes] = COALESCE([Likes], 0) + CASE WHEN #Song_like = 1 THEN 1
WHEN #Song_like = 0 THEN -1
ELSE 0 END
WHERE [Song_ID] = #SongID;
For the second part you can do something like this:
IF NOT EXISTS (SELECT 1
FROM [Users_Likes_Songs]
WHERE [UserID] = #User_ID
AND [SongID] = #SongID)
INSERT INTO [Users_Likes_Songs] (User_ID, SongID, [LikeSong])
VALUES (#User_ID, #SongID, #Song_like)
ELSE
UPDATE [Users_Likes_Songs]
SET [LikeSong] = #Song_like WHERE ([UserID] = #User_ID) AND ([SongID] = #SongID)
You can try this query in your procedure
UPDATE [songs]
SET [likes] = Isnull ([likes], 0) + ( CASE WHEN #Song_like THEN 1 ELSE -1 END)
WHERE [song_id] = #SongID
I'm developing a desktop application for inventory management.
I have 3 tables in SQL Server:
TRANSACTIONS
MATERIAL_TRANSACTION
TRANSACTION_DETAILS
I've created a stored procedure to insert as well as update all the above mentioned tables.
TRANSACTIONS is my master table. So, I use update query to update its columns.
But records of the other two tables, which are the detail tables, need to be deleted before inserting new rows in the database.
I'm unable to delete the rows in this stored procedure. Please help!
I've used the following SQL Server stored procedure
ALTER PROCEDURE [dbo].[SAVE_TRANSACTION]
#ID NVARCHAR(50),
#REF_NO NVARCHAR(50),
#VCH_DATE DATE,
#VCH_TYPE INT,
#CR_AC INT,
#DR_AC INT,
#DOCKET_NO NVARCHAR(50),
#TRANSPORT NVARCHAR(50),
#DELIVERY_NOTE NTEXT,
#S_NAR NVARCHAR(100),
#L_NAR NTEXT,
#IS_REVERSE_CHARGE INT,
#INVOICE_REF INT,
#BUYER NVARCHAR(50),
#BUYER_CONTACT NVARCHAR(50),
#BUYER_ADDRESS NTEXT,
#BUYER_GSTIN NVARCHAR(50),
#BUYER_STATE NVARCHAR(50),
#BUYER_REG_TYPE INT,
#MATERIAL_TRANSACTION dbo.TVP_MATERIAL_TRANSACTION READONLY,
#TRANSACTION_DETAILS dbo.TVP_TRANSACTION_DETAILS READONLY,
#RETURN INT OUTPUT
AS
DECLARE #TRAN_ID INT
BEGIN
SET NOCOUNT ON;
DELETE FROM MATERIAL_TRANSACTION
WHERE ID > 0
AND TRANSACTION_ID = #ID;
DELETE FROM TRANSACTION_DETAILS
WHERE ID > 0
AND TRANSACTION_ID = #ID;
IF (#ID = 0)
BEGIN
INSERT INTO dbo.TRANSACTIONS(REF_NO, VCH_DATE, VCH_TYPE, CR_AC, DR_AC,
DOCKET_NO, TRANSPORT, DELIVERY_NOTE,
S_NAR, L_NAR, IS_REVERSE_CHARGE,
INVOICE_REF, BUYER, BUYER_CONTACT, BUYER_ADDRESS,
BUYER_GSTIN, BUYER_STATE, BUYER_REG_TYPE)
VALUES (#REF_NO, #VCH_DATE, #VCH_TYPE, #CR_AC, #DR_AC,
#DOCKET_NO, #TRANSPORT, #DELIVERY_NOTE,
#S_NAR, #L_NAR, #IS_REVERSE_CHARGE,
#INVOICE_REF, #BUYER, #BUYER_CONTACT, #BUYER_ADDRESS,
#BUYER_GSTIN, #BUYER_STATE, #BUYER_REG_TYPE);
SET #TRAN_ID = ##IDENTITY
END
ELSE
BEGIN
UPDATE dbo.TRANSACTIONS
SET REF_NO = #REF_NO,
VCH_DATE = #VCH_DATE, VCH_TYPE = #VCH_TYPE,
CR_AC = #CR_AC, DR_AC = #DR_AC,
DOCKET_NO = #DOCKET_NO,
TRANSPORT = #TRANSPORT, DELIVERY_NOTE = #DELIVERY_NOTE,
S_NAR = #S_NAR, L_NAR = #L_NAR,
IS_REVERSE_CHARGE = #IS_REVERSE_CHARGE,
INVOICE_REF = #INVOICE_REF,
BUYER = #BUYER, BUYER_CONTACT = #BUYER_CONTACT,
BUYER_ADDRESS = #BUYER_ADDRESS,
BUYER_GSTIN = #BUYER_GSTIN, BUYER_STATE = #BUYER_GSTIN,
BUYER_REG_TYPE = #BUYER_REG_TYPE
WHERE
ID = #ID;
SET #TRAN_ID = #ID;
END
--UPDATE MATERIAL_TRANSACTION SET IS_DELETED=1 WHERE TRANSACTION_ID=#ID;
-- UPDATE TRANSACTION_DETAILS SET IS_DELETED=1 WHERE TRANSACTION_ID=#ID;
INSERT INTO TRANSACTION_DETAILS (TRANSACTION_ID, AC_ID, TRAN_TYPE,
CR_AMT, DR_AMT, AMT_PERCENT, IS_PARENT)
SELECT
#TRAN_ID, [AC_ID], [TRAN_TYPE],
[CR_AMT], [DR_AMT], [AMT_PERCENT], [IS_PARENT]
FROM
#TRANSACTION_DETAILS TVP
INSERT INTO MATERIAL_TRANSACTION (TRANSACTION_ID, PRODUCT_ID, QTY,
UNIT_ID, DESCRIPTION, HSN_CODE,
PRICE, DISCOUNT_AMT, DISCOUNT_PERCENT,
CGST_PERCENT, SGST_PERCENT, IGST_PERCENT,
CGST_AMT, SGST_AMT, IGST_AMT)
SELECT
#TRAN_ID, [PRODUCT_ID], [QTY],
[UNIT_ID], [DESCRIPTION], [HSN_CODE],
[PRICE], [DISCOUNT_AMT], [DISCOUNT_PERCENT],
[CGST_PERCENT], [SGST_PERCENT], [IGST_PERCENT],
[CGST_AMT], [SGST_AMT], [IGST_AMT]
FROM
#MATERIAL_TRANSACTION TVP
SELECT #RETURN = #TRAN_ID
END
I'm trying to consolidate some code but before I open this particular can of worms I wanted to find out from you guys. If I have several stored procedures...
sproc1 - "master proc" which sets #test
sproc2 - proc that executes if #test exists and returns both a resultset and (if possible) resets #serial
sproc3 - proc that executes if #test does not exist and returns both a resultset and (if possible) resets #serial
sproc1
#leftStack INT,
#leftTray INT,
#midStack INT,
#midTray INT,
#rightStack INT,
#rightTray INT
AS
DECLARE #soLineNumber varchar(50)
DECLARE #serial VARCHAR(50)
DECLARE #rack INT
DECLARE #tray INT
DECLARE #position INT
SELECT #test = oL.[SERIAL_NUMBER]
FROM [ROBOTICS_OPTICS_MECHUAT].[dbo].[AOF_ORDER_OPTICS] AS oL
WHERE NOT EXISTS
(
SELECT [SERIAL_NUMBER]
FROM [ROBOTICS_OPTICS_MECHUAT].[dbo].[AOF_OPTIC_RESULTS] AS rL
WHERE oL.[SERIAL_NUMBER] = rL.[SERIAL_NUMBER]
)
AND NOT EXISTS
(
SELECT [SERIAL_NUMBER]
FROM [ROBOTICS_OPTICS_MECHUAT].[dbo].[AOF_OPTIC_INSERTED] AS oI
WHERE oL.[SERIAL_NUMBER] = oI.[SERIAL_NUMBER]
)
-- AND oL.[SO_LINE_NUMBER] = #soLineNumber --pick regardless of SO line number, to reduce gaps between lines
AND ((oL.[RACK] = #leftStack AND oL.[TRAY] = #leftTray)
OR (oL.[RACK] = #midStack AND oL.[TRAY] = #midTray)
OR (oL.[RACK] = #rightStack AND oL.[TRAY] = #rightTray))
ORDER BY [SO_LINE_NUMBER] ASC
IF NULLIF(#test, '') IS NOT NULL
BEGIN
EXEC sproc2
END
IF NULLIF(#test, '') IS NULL
BEGIN
EXEC sproc3
END
UPDATE [ROBOTICS_OPTICS_MECHUAT].[dbo].[AOF_ORDER_OPTICS] SET [PICKED] = 'True' WHERE [SERIAL_NUMBER] = #serial
END
My questions:
1) how can I reset #serial from sproc2 and sproc3?
2) in an ADO recordset query, will the results from the executed stored procedures pull in, if so, how?
For this to work sproc2 and sproc3 should been defined like this:
CREATE PROC sproc2 #test VARCHAR(50), #serial VARCHAR(50) OUTPUT
What this does is, it sends the value of #test as a value param. The OUTPUT keyword on #serial enables you to keep track of any changes done on #serial.
I'm using SQL Server 2008 R2. I have a View [EmployeeMaster] from a Linked Server and a table [EmployeeDetails] in database. i have a service which run at 12 AM everyday calling a stored procedure which sync the table with view. ie, stored procedure check and update each row in [EmployeeDetails] with the matching row from view. My stored procedure goes like this.
CREATE PROCEDURE usp_OracleSyncUpdate
AS
CREATE TABLE #ActiveEmployees (
RowID int IDENTITY(1, 1),
[EmployeeId] nvarchar(50),
)
DECLARE #NumberRecords int, #RowCount int
DECLARE #EmployeeId nvarchar(50)
,#EmployeeName nvarchar(50)
,#EmployeeLastName nvarchar(50)
,#EmployeeCategory nvarchar(50)
,#ContactNo nvarchar(50)
,#Email nvarchar(50)
,#Gender nvarchar(50)
,#JoiningDate DATETIME
-- into the temporary table
INSERT INTO #ActiveEmployees ([EmployeeId])
SELECT [EMPLOYEE_NUMBER]
FROM [dbo].[EmployeeMaster]
WHERE [EMPLOYEE_NUMBER] IN (
SELECT EmployeeId
FROM [dbo].[EmployeeDetails]
)
-- Get the number of records in the temporary table
SET #NumberRecords = ##ROWCOUNT
SET #RowCount = 1
-- loop through all records in the temporary table
-- using the WHILE loop construct
WHILE #RowCount <= #NumberRecords
BEGIN
SELECT #EmployeeId = EmployeeId
FROM #ActiveEmployees
WHERE RowID = #RowCount
SELECT #EmployeeName = EmployeeName FROM [dbo].[EmployeeDetails] WHERE [EmployeeId] = #EmployeeId
IF(LTRIM(RTRIM(#EmployeeName)) <> (SELECT LTRIM(RTRIM([FIRST_NAME])) FROM [dbo].[EmployeeMaster] WHERE [EMPLOYEE_NUMBER] = #EmployeeId))
BEGIN
UPDATE [dbo].[EmployeeDetails] SET EmployeeName = (SELECT LTRIM(RTRIM([FIRST_NAME])) FROM [dbo].[EmployeeMaster] WHERE [EMPLOYEE_NUMBER] = #EmployeeId)
WHERE EmployeeId = #EmployeeId
END
SELECT #EmployeeLastName = EmployeeLastName FROM [dbo].[EmployeeDetails] WHERE [EmployeeId] = #EmployeeId
IF(LTRIM(RTRIM(#EmployeeLastName)) <> (SELECT LTRIM(RTRIM([LAST_NAME])) FROM [dbo].[EmployeeMaster] WHERE [EMPLOYEE_NUMBER] = #EmployeeId))
BEGIN
UPDATE [dbo].[EmployeeDetails] SET EmployeeLastName = (SELECT LTRIM(RTRIM([LAST_NAME])) FROM [dbo].[EmployeeMaster] WHERE [EMPLOYEE_NUMBER] = #EmployeeId)
WHERE EmployeeId = #EmployeeId
END
SELECT #EmployeeCategory = [Category] FROM [dbo].[EmployeeCategory] WHERE [EmployeeCategoryId] = (SELECT [EmployeeCategoryId] FROM [dbo].[EmployeeDetails] WHERE [EmployeeId] = #EmployeeId)
IF(LTRIM(RTRIM(#EmployeeCategory)) <> (SELECT LTRIM(RTRIM([JOB_NAME])) FROM [dbo].[EmployeeMaster] WHERE [EMPLOYEE_NUMBER] = #EmployeeId))
BEGIN
UPDATE [dbo].[EmployeeDetails] SET [EmployeeCategoryId] = (SELECT [EmployeeCategoryId] FROM [dbo].[EmployeeCategory] WHERE [Category] = (SELECT LTRIM(RTRIM([JOB_NAME])) FROM [dbo].[EmployeeMaster] WHERE [EMPLOYEE_NUMBER] = #EmployeeId))
WHERE EmployeeId = #EmployeeId
END
SELECT #Email = Email FROM [dbo].[EmployeeDetails] WHERE [EmployeeId] = #EmployeeId
IF(LTRIM(RTRIM(#Email)) <> (SELECT LTRIM(RTRIM([EMAIL_ADDRESS])) FROM [dbo].[EmployeeMaster] WHERE [EMPLOYEE_NUMBER] = #EmployeeId))
BEGIN
UPDATE [dbo].[EmployeeDetails] SET Email = (SELECT LTRIM(RTRIM([EMAIL_ADDRESS])) FROM [dbo].[EmployeeMaster] WHERE [EMPLOYEE_NUMBER] = #EmployeeId)
WHERE EmployeeId = #EmployeeId
END
SELECT #Gender = Gender FROM [dbo].[EmployeeDetails] WHERE [EmployeeId] = #EmployeeId
IF(LTRIM(RTRIM(#Gender)) <> (SELECT LTRIM(RTRIM([GENDER])) FROM [dbo].[EmployeeMaster] WHERE [EMPLOYEE_NUMBER] = #EmployeeId))
BEGIN
UPDATE [dbo].[EmployeeDetails] SET Gender = (SELECT LTRIM(RTRIM([GENDER])) FROM [dbo].[EmployeeMaster] WHERE [EMPLOYEE_NUMBER] = #EmployeeId)
WHERE EmployeeId = #EmployeeId
END
SELECT #JoiningDate = JoiningDate FROM [dbo].[EmployeeDetails] WHERE [EmployeeId] = #EmployeeId
IF(LTRIM(RTRIM(#JoiningDate)) <> (SELECT LTRIM(RTRIM([DATE_OF_JOINING])) FROM [dbo].[EmployeeMaster] WHERE [EMPLOYEE_NUMBER] = #EmployeeId))
BEGIN
UPDATE [dbo].[EmployeeDetails] SET JoiningDate = (SELECT LTRIM(RTRIM([DATE_OF_JOINING])) FROM [dbo].[EmployeeMaster] WHERE [EMPLOYEE_NUMBER] = #EmployeeId)
WHERE EmployeeId = #EmployeeId
END
SET #RowCount = #RowCount + 1
END
-- drop the temporary table
DROP TABLE #ActiveEmployees
Its working and it updates the columns. now the table has 26196 Records and it takes about 23:56 minutes to execute this stored procedure. In future the records will keep increasing and the execution time will be more.
Is there any way to bring down the execution time (suggest some optimization for the query )?
Or is there any other way i can sync the two table?
Or Is there any way to calculate the execution time for future also and i can set the connection timeout according to that?
Here is my final code
alter PROCEDURE usp_OracleSyncUpdate
AS
UPDATE ed
SET ed.[EmployeeName] = LTRIM(RTRIM(em.FIRST_NAME)),
ed.EmployeeLastName = LTRIM(RTRIM(em.LAST_NAME)),
ed.EmployeeCategoryId = ec.EmployeeCategoryId,
ed.Email = isnull(ed.Email,em.[EMAIL_ADDRESS]),
ed.[ContactNo] = isnull(ed.[ContactNo],em.ContactNo),
ed.Gender = em.Gender,
ed.JoiningDate = em.[DATE_OF_JOINING]
FROM dbo.EmployeeDetails ed
INNER JOIN [EmployeeMaster] em ON ed.EmployeeId = em.[EMPLOYEE_NUMBER]
INNER JOIN dbo.EmployeeCategory ec ON ec.Category = em.[JOB_NAME]
Thanks #marc_s
Get rid of the RBAR (row-by-agonizing-row) processing - relational databases work in sets of data - use a single set-based UPDATE statement and you're done.
Something along the lines of :
CREATE PROCEDURE usp_OracleSyncUpdate
AS
CREATE TABLE #ActiveEmployees (
RowID int IDENTITY(1, 1),
[EmployeeId] nvarchar(50),
)
-- into the temporary table
INSERT INTO #ActiveEmployees ([EmployeeId])
SELECT [EMPLOYEE_NUMBER]
FROM [dbo].[EmployeeMaster]
WHERE [EMPLOYEE_NUMBER] IN (SELECT EmployeeId
FROM [dbo].[EmployeeDetails])
UPDATE dbo.EmployeeDetails
SET ed.EmployeeName = LTRIM(RTRIM(ae.FIRST_NAME)),
ed.EmployeeLastName = (SELECT LTRIM(RTRIM(ae.LAST_NAME)),
ed.EmployeeCategoryId = ec.EmployeeCategoryId,
ed.Email = ae.Email,
ed.Gender = ae.Gender,
ed.JoiningDate = ae.JoiningDate
FROM dbo.EmployeeDetails ed
INNER JOIN #ActiveEmployees ae ON ed.EmployeeId = ae.EmployeeId
INNER JOIN dbo.EmployeeCategory ec ON .......
WHERE EmployeeId = #EmployeeId
I didn't know how the EmployeeCategory table is linked to the others - you'll need to add that JOIN condition on the INNER JOIN line there.
Also, quite possibly, you could also eliminate that temporary table altogether and just update EmployeeDetails directly from EmployeeMaster as a second step to save memory and processing time.
Well, instead of a loop do it in one sql statement and be done with it. Seriously.
I see a loop and I see a ton of indivisual statements and I can envision that being ONE UPATE STATEMENT ONLY.
On top, this is not "hugh table". It is tiny. Super tiny. One million rows is small. This has not even 27000 rows. You just abuse the server it by making a "Programmer approach" - loop, way too many statement. Use a set based approach and your whole loop can be written as ONE STATEMENT.
Comparing two codes below,both do the same,but with slighty differences:
ALTER procedure [dbo].[SP_USUARIOS_UPDATE]
#usu_ds varchar(100),
#usu_dt_lst_log datetime,
#usu_ds_senha varchar(255),
#usu_ds_email varchar(100)
as
begin
declare #usu_ID int;
create table #TempUser
(
UsuID int,
Senha varchar(255),
Email varchar(100)
)
select Usuarios.usu_ID as UsuID,Usuarios.usu_ds_senha as Senha,
Usuarios.usu_ds_email as Email into #TempUser from Usuarios where Usuarios.usu_ds = #usu_ds
if(#usu_ds_senha is null)
begin
set #usu_ds_senha = (select #TempUser.Senha from #TempUser);
end
if(#usu_ds_email is null)
begin
set #usu_ds_email = (select #TempUser.Email from #TempUser);
end
set #usu_ID = (select #TempUser.UsuID from #TempUser);
update Usuarios set usu_dt_lst_log =
#usu_dt_lst_log,usu_ds_senha = #usu_ds_senha,usu_ds_email = #usu_ds_email where usu_ID = #usu_ID
end
AND
ALTER procedure [dbo].[SP_USUARIOS_UPDATE]
#usu_ds varchar(100),
#usu_dt_lst_log datetime,
#usu_ds_senha varchar(255),
#usu_ds_email varchar(100)
as
begin
declare #usu_ID int;
if(#usu_ds_senha is null)
begin
set #usu_ds_senha = (select Usuarios.usu_ds_senha from Usuarios where Usuarios.usu_ds = #usu_ds);
end
if(#usu_ds_email is null)
begin
set #usu_ds_email = (select Usuarios.usu_ds_email from Usuarios where Usuarios.usu_ds = #usu_ds);
end
set #usu_ID = (select Usuarios.UsuID from Usuarios where Usuarios.usu_ds = #usu_ds);
update Usuarios set usu_dt_lst_log =
#usu_dt_lst_log,usu_ds_senha = #usu_ds_senha,usu_ds_email = #usu_ds_email where usu_ID = #usu_ID
end
Do you think the first is faster than second in performance,i mean,first code use temp table (#TempUser) to store 3 fields from the real table.Second code,select all fields from the real table one by one.
What code is best optimized?
First -- if it's possible for your passed parameters to be null, you need to set defaults. For example:
#usu_ds_email varchar(100) = null
...
Otherwise, your null checks further down will never come into play -- the procedure will just fail.
Second -- just run a direct update. It seems like you're pushing a lot of data back and forth unnecessarily. E.g., you don't need to create a temp table from the table you're going to update, and then turn right around and update your table from the temp table you just created.
ALTER procedure [dbo].[SP_USUARIOS_UPDATE]
#usu_ds varchar(100),
#usu_dt_lst_log datetime,
#usu_ds_senha varchar(255) = null,
#usu_ds_email varchar(100) = null
as
begin
update Usuarios
set usu_dt_lst_log = #usu_dt_lst_log,
usu_ds_senha = isnull(#usu_ds_senha, usu_ds_senha),
usu_ds_email = isnull(#usu_ds_email, usu_ds_email)
where usu_ID = #usu_ds
end
Third way...
ALTER procedure [dbo].[SP_USUARIOS_UPDATE]
#usu_ds varchar(100),
#usu_dt_lst_log datetime,
#usu_ds_senha varchar(255) = null,
#usu_ds_email varchar(100) = null
as
begin
update x
set x.usu_dt_lst_log = #usu_dt_lst_log,
x.usu_ds_senha = ISNULL(#usu_ds_senha, x.usu_ds_senha),
x.usu_ds_email = ISNULL(#usu_ds_email, x.usu_ds_email)
from Usuarios x where x.usu_ds = #usu_ds
end
Which one runs faster? Set a profiler, run both, and get some real data: then you'll know.
However, based on my own previous experiences, the Temp Table has always been faster for me.