I have a table Sample and another SampleLog
With these structure I want to write codes to log. You can see my codes after structures of tables
CREATE TABLE [dbo].[Sample](
[ID] [int] NULL,
[Name] [varchar](10) NULL
)
CREATE TABLE [dbo].[SampleLog](
[ID] [int] NULL,
[Name] [varchar](10) NULL,
[Date] [datetime] NULL,
[UserName] [varchar](100) NULL,
[Type] [char](1) NULL
)
I have written this code but it doesn't work for Delete and Update .
CREATE TRIGGER SampleTrigger ON Sample
AFTER INSERT, UPDATE, DELETE
AS
DECLARE
#ID int ,
#Name varchar(10),
#Date datetime,
#UserName VARCHAR(128) ,
#Type CHAR(1) ,
#sql nvarchar(500)
SELECT
#UserName = SYSTEM_USER ,
#Date = CONVERT(VARCHAR(8), GETDATE(), 112)
+ ' ' + CONVERT(VARCHAR(12), GETDATE(), 114)
IF EXISTS (SELECT * FROM inserted)
BEGIN
IF EXISTS (SELECT * FROM deleted)
BEGIN
SELECT #Type = 'U'
select #ID = ID from deleted
select #Name = Name from deleted
END
ELSE
BEGIN
SELECT #Type = 'I'
select #ID = ID from inserted
select #Name = Name from inserted
END
END
ELSE
BEGIN
SELECT #Type = 'D'
select #ID = ID from deleted
select #Name = Name from deleted
END
insert into SampleLog(ID, Name, Date, UserName, Type)
values(#ID, #Name, #Date, #UserName, #Type)
SQL Server gives me this error
The row values updateed or deleted either do not make the row unique or they alter multiple rows(2 rows)
You've coded for single row updates and deletes. Think sets!
CREATE TRIGGER SampleTrigger ON Sample after INSERT, UPDATE, DELETE
AS
SET NOCOUNT ON;
insert into SampleLog
(ID,Name,Date,UserName,Type)
SELECT
D.ID, D.NAME, GETDATE(), SYSTEM_USER,
CASE WHEN I.ID IS NULL THEN 'D' ELSE 'U' END
FROM
DELETED D
LEFT JOIN
INSERTED I ON D.ID = I.ID
UNION ALL
SELECT
I.ID, I.NAME, GETDATE(), SYSTEM_USER, 'I'
FROM
INSERTED I
LEFT JOIN
DELETED D ON D.ID = I.ID
WHERE
D.ID IS NULL
GO
Related
I am building a stored procedure that executes 10-12 SQL statements. I'm getting an error 1172, Result consisted of more than one row. I'm trying to figure out which statement is responsible.
The most obvious way is to return the SQL of the statement that raised the error.
Here is my exit handler:
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS #n = NUMBER, #c = ROW_COUNT;
GET DIAGNOSTICS CONDITION #n
#s = RETURNED_SQLSTATE,
#m = MESSAGE_TEXT,
#e = MYSQL_ERRNO;
ROLLBACK;
SELECT #s as RETURNED_SQLSTATE, #e as MYSQL_ERRNO, #m as MESSAGE_TEXT, #n as NUMBER, #c as ROW_COUNT;
END;
What can I add so that it will tell me which of my SQL statements generated the error?
For reference, here is the full stored procedure:
DROP PROCEDURE IF EXISTS `unlink_item`;
CREATE PROCEDURE `unlink_item` (
IN item_id varchar(36),
IN parent_id varchar(36),
IN author varchar(64),
IN conversation_id varchar(36),
IN transaction_id varchar(36)
)
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS #n = NUMBER, #c = ROW_COUNT;
GET DIAGNOSTICS CONDITION #n
#s = RETURNED_SQLSTATE,
#m = MESSAGE_TEXT,
#e = MYSQL_ERRNO;
ROLLBACK;
SELECT #s as RETURNED_SQLSTATE, #e as MYSQL_ERRNO, #m as MESSAGE_TEXT, #n as NUMBER, #c as ROW_COUNT;
END;
START TRANSACTION;
SET #when = now();
-- identify the record we are supposed to delete --
SET #deleted = '123';
SELECT `id`
FROM `item_contains`
WHERE `parent_id` = parent_id
AND `child_id` = item_id
INTO #deleted;
-- delete the record --
DELETE FROM `item_contains`
WHERE `id` = #deleted;
-- update the change history for the item_contains table --
INSERT INTO `change_history` (
`date_time`,
`author`,
`action`,
`table_name`,
`record_id`,
`conversation_id`,
`transaction_id`
) VALUES (
#when,
author,
'delete',
'item_contains',
#deleted,
conversation_id,
transaction_id
);
-- update the change history for the parent item --
INSERT INTO `change_history` (
`date_time`,
`author`,
`action`,
`table_name`,
`record_id`,
`conversation_id`,
`transaction_id`
) VALUES (
#when,
author,
concat('unlink from ',parent_id),
'item',
item_id,
conversation_id,
transaction_id
);
-- update the change history for the item being unlinked --
INSERT INTO `change_history` (
`date_time`,
`author`,
`action`,
`table_name`,
`record_id`,
`conversation_id`,
`transaction_id`
) VALUES (
#when,
author,
concat('unlink ',item_id, ' from this'),
'item',
parent_id,
conversation_id,
transaction_id
);
-- if the unlinked item is now orphaned either delete it if it is empty, or re-attach it somewhere to make it accessible --
SET #instances = 0;
SELECT count(`id`)
FROM `item_contains`
WHERE `child_id` = item_id
INTO #instances;
IF ( #instances = 0 ) THEN
SET #children = 0;
SELECT count(`id`)
FROM `item_contains`
WHERE `parent_id` = item_id
INTO #children;
IF ( #children = 0 ) THEN
-- delete the now inaccessible item from the database --
DELETE FROM `item`
WHERE `id` = item_id;
-- update the change history for that item --
INSERT INTO `change_history` (
`date_time`,
`author`,
`action`,
`table_name`,
`record_id`,
`conversation_id`,
`transaction_id`
) VALUES (
#when,
author,
'delete',
'item',
item_id,
conversation_id,
transaction_id
);
ELSE
-- get the ID of the orphan folder --
SET #orphan_id = '123';
SELECT `id`
FROM `item`
WHERE `name` = '### orphans ###'
INTO #orphan_id;
-- move the item into the orphan folder --
SET #inserted = uuid();
INSERT INTO `item_contains` (
`id`,
`parent_id`,
`child_id`
) VALUES (
#inserted,
#orphan_id,
item_id
);
-- update the change history to reflect the orphaning of the item --
INSERT INTO `change_history` (
`date_time`,
`author`,
`action`,
`table_name`,
`record_id`,
`conversation_id`,
`transaction_id`
) VALUES (
#when,
author,
'orphaned',
'item',
item_id,
conversation_id,
transaction_id
);
END IF;
END IF;
SELECT
0 AS `RETURNED_SQLSTATE`,
0 AS `MYSQL_ERRNO`,
'Item unlinked' AS `MESSAGE_TEXT`,
1 as `ROW_COUNT`;
COMMIT;
END;
UPDATE: The root problem was in the first SELECT statement:
SELECT `id` FROM `item_contains`
WHERE `parent_id` = parent_id
AND `child_id` = item_id
I had assumed that the left parent_id would be the one from item_contains and the right parent_id would be the stored procedure parameter. I was mistaken. Both are interpreted as the stored procedure parameter. The solution was to alias the table and refer to the fields via the alias, like so:
SELECT ic.id FROM item_contains AS ic
WHERE ic.parent_id = parent_id
AND ic.child_id = item_id
HOWEVER: the original question still stands:
Is there something that I can add to my EXIT HANDLER that will tell me WHERE in my stored procedure that the error was raised?
All SELECT ... INTO statements must return only one row.
For example, The below code may return more than 1 record:
SELECT `id`
FROM `item_contains`
WHERE `parent_id` = parent_id
AND `child_id` = item_id
INTO #deleted;
You can debug statement storing the result in another variable and select:
SELECT count(*)
FROM `item_contains`
WHERE `parent_id` = parent_id
AND `child_id` = item_id
INTO #supposed_to_delete;
SELECT #supposed_to_delete; /*you will see the value after execute*/
Another way to make sure only one record (not recommended) is adding a limit
SELECT `id`
FROM `item_contains`
WHERE `parent_id` = parent_id
AND `child_id` = item_id
LIMIT 1 /* <-- force to return only one record */
INTO #deleted;
I have the next stored procedure which inserts values into 2 tables. To the 2nd table I insert id's of 2 last inserts from 1st table
However, I would like to rewrite it with one query instead of using temp table and while.
CREATE PROCEDURE CurrencyExhange
AS
DECLARE #TmpTable Table
(
ID int IDENTITY(1,1) NOT NULL PRIMARY KEY,
BillID int,
Amount decimal,
Rate decimal,
Date date
)
INSERT INTO #TmpTable
SELECT T.[BillID]
,[Amount]
,CR.Rate
,CR.Date
FROM [FinanceLabkovich].[dbo].[Transactions] T
JOIN [FinanceLabkovich].[dbo].Bills B ON B.BillID = T.BillID
JOIN [FinanceLabkovich].[dbo].Currencies C ON C.CurrencyID=B.CurrencyID
JOIN [FinanceLabkovich].[dbo].CurrencyRates CR ON CR.CurrencyRateID=FinanceLabkovich.dbo.GetRate(T.Date)
WHERE LOWER(C.Name)='usd' AND T.Income=1
ORDER BY T.Date
DECLARE #ToBillID int = (SELECT BillID FROM [FinanceLabkovich].[dbo].Bills B WHERE B.Name='Purse')
DECLARE #i int = (SELECT MIN(Id) FROM #TmpTable)
DECLARE #maxId int = (SELECT MAX(Id) FROM #TmpTable)
DECLARE #TransactionID int, #ToTransactionID int, #Amount decimal
DECLARE #date date
WHILE (#i<=#maxId)
BEGIN
SET #date = (SELECT Date FROM #TmpTable WHERE ID=#i)
SET #Amount = (SELECT AmountUSD FROM [FinanceLabkovich].[dbo].Cashflow WHERE Date=#date)
IF #Amount > 0
BEGIN
INSERT INTO [FinanceLabkovich].[dbo].[Transactions] (Name,BillID,ToBillID,Amount,Date,Income)
SELECT "Name"='Currency exhange'
,BillID
,#ToBillID
,#Amount
,T.Date
,"Income"=0
FROM #TmpTable T
WHERE ID=#i
SET #TransactionID = ##IDENTITY
INSERT INTO [FinanceLabkovich].[dbo].[Transactions] (Name,BillID,ToBillID,Amount,Date,Income)
SELECT "Name"='Currency exhange'
,#ToBillID
,BillID
,#Amount*Rate AS Total
,Date
,"Income"=1
FROM #TmpTable WHERE ID=#i
SET #ToTransactionID = ##IDENTITY
INSERT INTO [FinanceLabkovich].[dbo].[Transfers]
SELECT #TransactionID, #ToTransactionID
END
SET #i += 1
END
Any help appreciated.
SELECT
PDADate, T.Merchandizer_ID, T.Merchandizer, Merchandizer_LoginName,
STORE_ID, STORE_CODE, STORE_NAME,
ACCOUNT_ID, ACCOUNT_NAME, Account_Store_Format_Id, Account_Store_Format,
StoreType_Id, StoreType, T.Listid, T.Listname,
T.TimeIn, T.TimeOut, T.PlannedDate, T.Reason, TaskCode, TotalTime
FROM
[dbo].Report_RD_Coverage T
INNER JOIN
#TempLocationH TL ON TL.LocationId=T.Location_Id
WHERE
CONVERT(Date, PDADate) Between (#Start_Date) AND Isnull(#End_Date, #CurrentDate)
AND T.Account_Id IN
(SELECT
CASE WHEN #Account_Id IS NULL THEN T.Account_Id
ELSE (SELECT * FROM UDF_SplitString(#Account_Id,','))
END
)
AND T.StoreType_Id IN
(SELECT
CASE WHEN #StoreType_Id IS NULL THEN T.StoreType_Id
ELSE (SELECT * FROM UDF_SplitString(#StoreType_Id,','))
END
)
AND T.Store_Id IN
(SELECT
CASE WHEN #Store_Id IS NULL THEN T.Store_Id
ELSE (SELECT * FROM UDF_SplitString(#Store_Id,','))
END
)
If #Account_Id, #StoreType_Id and #Store_Id are null the it should select all the ACCOUNT_ID, STORETYPE_ID and STORE_ID otherwise based on parameter value it should filter.
UDF_SplitString is the function to split up comma-separated strings, and its return value is a table like:
- 1
- 2
- 3
I'm getting this error:
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
CASE must return a scalar value, so try this variation instead:
select PDADate, T.Merchandizer_ID, T.Merchandizer, Merchandizer_LoginName, STORE_ID, STORE_CODE,
STORE_NAME, ACCOUNT_ID, ACCOUNT_NAME, Account_Store_Format_Id, Account_Store_Format,
StoreType_Id, StoreType, T.Listid, T.Listname, T.TimeIn, T.TimeOut, T.PlannedDate,
T.Reason, TaskCode, TotalTime
from [dbo].Report_RD_Coverage T
inner join #TempLocationH TL on TL.LocationId = T.Location_Id
where CONVERT(date, PDADate) between (#Start_Date)
and Isnull(#End_Date, #CurrentDate)
and (
#Account_Id is null
or T.Account_Id in (
select *
from UDF_SplitString(#Account_Id, ',')
)
)
and (
#StoreType_Id is null
or T.StoreType_Id in (
select *
from UDF_SplitString(#StoreType_Id, ',')
)
)
and (
#Store_Id is null
or T.Store_Id in (
select *
from UDF_SplitString(#Store_Id, ',')
) end
)
I tried this and reached very closer but you have to do something from what I found a link.
This is my try. the only thing you need to build is the #udf data.
declare #Store_Id INT;
declare #Account_Id INT;
DECLARE #UDF[9] OF VARCHAR(30);
set #Store_Id = 99 --NULL
set #Account_Id = 15
SET #UDF = '11,12,13,14,15,16'
SELECT #Account_Id AS ACID
WHERE CAST(#Account_Id AS VARCHAR(6)) IN (
CASE WHEN #Store_Id IS NULL THEN CAST(#Account_Id AS VARCHAR(6))
ELSE #UDF END
The link is at
http://www.codeproject.com/Questions/473174/CreateplusArrayplusinplusSqlplusServer
DECLARE #INSTR as VARCHAR(MAX)
SET #INSTR = '2,3,177,'
DECLARE #SEPERATOR as VARCHAR(1)
DECLARE #SP INT
DECLARE #VALUE VARCHAR(1000)
SET #SEPERATOR = ','
CREATE TABLE #tempTab (id int not null)
WHILE PATINDEX('%' + #SEPERATOR + '%', #INSTR ) <> 0
BEGIN
SELECT #SP = PATINDEX('%' + #SEPERATOR + '%',#INSTR)
SELECT #VALUE = LEFT(#INSTR , #SP - 1)
SELECT #INSTR = STUFF(#INSTR, 1, #SP, '')
INSERT INTO #tempTab (id) VALUES (#VALUE)
END
SELECT * FROM myTable WHERE id IN **(SELECT id FROM #tempTab)**
DROP TABLE #tempTab
you can extract for the sql in bold and the logic how to create temp table and its data and I hope you will get what you want.
> This is the my right solultion........now its working correctly
CREATE TABLE #Store_Id (StoreID varchar(20))
IF #Store_Id != '0'
BEGIN
INSERT INTO #Store_Id
SELECT data FROM UDF_SplitString(#Store_Id,',')
END
ELSE
BEGIN
INSERT INTO #Store_Id
SELECT '0'
END
CREATE TABLE #StoreType_Id (StoreTypeID varchar(20))
IF #StoreType_Id != '0'
BEGIN
INSERT INTO #StoreType_Id
SELECT data FROM UDF_SplitString(#StoreType_Id,',')
END
ELSE
BEGIN
INSERT INTO #StoreType_Id
SELECT '0'
END
CREATE TABLE #Account_Id (AccountID varchar(20))
IF #Account_Id != '0'
BEGIN
INSERT INTO #Account_Id
SELECT data FROM UDF_SplitString(#Account_Id,',')
END
ELSE
BEGIN
INSERT INTO #Account_Id
SELECT '0'
END
INSERT INTO #FinalTable(VisitDate,Merchandizer_Id,Merchandizer,MerchandizerLogin,StoreId,StoreCode,StoreName,AccountId,AccountName,
Account_Store_Format_Id,Account_Store_Format,StoreTypeId ,StoreType ,ListId ,ListName,TimeIn ,TimeOut,PlannedDate ,Reason ,TaskCode,TotalTime)
SELECT Visit_Date,T.Merchandizer_ID,T.Merchandizer,Merchandizer_LoginName,STORE_ID,STORE_CODE,STORE_NAME,ACCOUNT_ID,ACCOUNT_NAME,
Account_Store_Format_Id,Account_Store_Format,StoreType_Id,
StoreType,T.Listid,T.Listname,T.TimeIn,T.TimeOut,T.PlannedDate,T.Reason,TaskCode,TotalTime
FROM [dbo].Report_RD_Coverage T
INNER JOIN #TempLocationH TL ON TL.LocationId=T.Location_Id
INNER JOIN #Store_Id on CONVERT(VARCHAR,t.Store_Id) = CASE WHEN #Store_Id = '0' THEN convert(VARCHAR,t.Store_Id) ELSE StoreID END
INNER JOIN #StoreType_Id on CONVERT(VARCHAR,t.StoreType_Id) = CASE WHEN #StoreType_Id = '0' THEN convert(VARCHAR,t.StoreType_Id) ELSE StoreTypeID END
INNER JOIN #Account_Id on CONVERT(VARCHAR,t.Account_Id) = CASE WHEN #Account_Id = '0' THEN convert(VARCHAR,t.Account_Id) ELSE AccountID END
WHERE CONVERT(Date,PDADate) Between #Start_Date AND #End_Date
Need help to inserting 100 records in loop, continue where it stop from and break once the records are completed.
Alter PROCEDURE ETL.ETLPurge #PurgeYear INT
AS
BEGIN
DECLARE #BatchId INT = (SELECT BatchId FROM Tracker)
declare #Count int
declare #batchsize int
set #batchsize = 100
--set #Count = ##rowcount
SELECT DISTINCT IDENTITY(INT,1,1) AS ID, MC.ID
INTO #tmp
FROM Contact MC
JOIN Extract CE
ON MC.ExtractID = CE.ExtractID
LEFT JOIN Application A
ON MC.ID = A.ID
WHERE CE.Year < #PurgeYear
AND A.ApplicationId IS NULL
--declare #counter bigint
--set #counter = 1
--while #counter < 500
--Begin
--while 1 = 1
--begin
Create NONCLUSTERED INDEX nix_ID
on #tmp(ID)
--while 1=1
--begin
INSERT
--Top (#batchsize)
INTO Table1 (Values ………)
(
SELECT top (#batchsize)
#BatchID,
Values ……..)
FROM Contact MC
inner join
#tmp TK on MC.ContactID = TK.ContactID
--where TK.ID between #batchsize and #ctr + 1
)
if ##ROWCOUNT < #batchsize
break
end
-- --continue
-- --if ##ROWCOUNT = 0
-- Break
end
--end
--number of rows inserted should equal number of rows deleted.
Ok.
Here is my sample.
What happened to me is that my dba "team" .. screwed up setting Replication for us.
So .. over the weekend, working like dogs.... we had to write some code to "pull over" records from a source database to a destination database, where the structure of the database was the same. We had to fake-out some replication.
We had 8,000,000 rows, and we would pull them over 10,000 at a time.
Below, I have about 1000 rows, and set the "number of rows to pull at one time" to 333.
I also put a #MaximumLoopCounter as a "just in case". I didn't want to accidentally create a endless loop.
The sample below bases its "while" logic on "while exists (some records on the source-database-table that are not in the destination-database-table)"...keep grabbing those records.
I'm trying to help you answer your question. In our case, we finally got replication working correctly, and we were able to abandon these scripts. It was NOT a fun weekend.
/* SETUP */
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[CodeCategorySourceTable]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
BEGIN
DROP TABLE [dbo].[CodeCategorySourceTable]
END
GO
CREATE TABLE [dbo].[CodeCategorySourceTable] (
CodeCategoryUUID [uniqueidentifier] not null default NEWSEQUENTIALID() ,
CodeCategoryName varchar(64) not null
)
GO
ALTER TABLE [dbo].[CodeCategorySourceTable] ADD CONSTRAINT PK_CodeCategorySourceTable_CodeCategoryUUID
PRIMARY KEY CLUSTERED (CodeCategoryUUID)
GO
ALTER TABLE [dbo].[CodeCategorySourceTable] ADD CONSTRAINT CK_CodeCategorySourceTable_CodeCategoryName_UNIQUE
UNIQUE (CodeCategoryName)
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[CodeCategoryDestinationTable]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
BEGIN
DROP TABLE [dbo].[CodeCategoryDestinationTable]
END
GO
CREATE TABLE [dbo].[CodeCategoryDestinationTable] (
CodeCategoryUUID [uniqueidentifier] not null default NEWSEQUENTIALID() ,
CodeCategoryName varchar(64) not null
)
GO
ALTER TABLE [dbo].[CodeCategoryDestinationTable] ADD CONSTRAINT PK_CodeCategoryDestinationTable_CodeCategoryUUID
PRIMARY KEY CLUSTERED (CodeCategoryUUID)
GO
ALTER TABLE [dbo].[CodeCategoryDestinationTable] ADD CONSTRAINT CK_CodeCategoryDestinationTable_CodeCategoryName_UNIQUE
UNIQUE (CodeCategoryName)
GO
declare #AlreadyExistingCodeCategoryUUID01 uniqueidentifier
declare #AlreadyExistingCodeCategoryUUID03 uniqueidentifier
declare #AlreadyExistingCodeCategoryUUID02 uniqueidentifier
declare #AlreadyExistingOldCodeCategoryName01 varchar(64)
declare #AlreadyExistingOldCodeCategoryName02 varchar(64)
declare #AlreadyExistingOldCodeCategoryName03 varchar(64)
declare #AlreadyExistingNewCodeCategoryName01 varchar(64)
declare #AlreadyExistingNewCodeCategoryName02 varchar(64)
declare #AlreadyExistingNewCodeCategoryName03 varchar(64)
select #AlreadyExistingCodeCategoryUUID01 = NEWID(), #AlreadyExistingCodeCategoryUUID02 = NEWID(), #AlreadyExistingCodeCategoryUUID03 = NEWID()
select #AlreadyExistingNewCodeCategoryName01 = 'NewOne', #AlreadyExistingNewCodeCategoryName02 = 'NewTwo', #AlreadyExistingNewCodeCategoryName03 = 'NewThree'
select #AlreadyExistingOldCodeCategoryName01 = 'OldOne', #AlreadyExistingOldCodeCategoryName02 = 'OldTwo', #AlreadyExistingOldCodeCategoryName03 = 'OldThree'
Insert Into [dbo].[CodeCategorySourceTable] ( CodeCategoryUUID , CodeCategoryName )
Select top 1000 NEWID() , convert(varchar(40), NEWID()) + 'Name' from dbo.sysobjects so1 cross join dbo.sysobjects so2
Insert Into [dbo].[CodeCategorySourceTable] ( CodeCategoryUUID , CodeCategoryName )
select #AlreadyExistingCodeCategoryUUID01, #AlreadyExistingNewCodeCategoryName01
UNION ALL select #AlreadyExistingCodeCategoryUUID02, #AlreadyExistingNewCodeCategoryName02
UNION ALL select #AlreadyExistingCodeCategoryUUID03, #AlreadyExistingNewCodeCategoryName03
select count(*) from [dbo].[CodeCategorySourceTable] as CodeCategorySourceTableCOUNT
Insert Into [dbo].[CodeCategoryDestinationTable] ( CodeCategoryUUID , CodeCategoryName )
select #AlreadyExistingCodeCategoryUUID01, #AlreadyExistingOldCodeCategoryName01
UNION ALL select #AlreadyExistingCodeCategoryUUID02, #AlreadyExistingOldCodeCategoryName02
UNION ALL select #AlreadyExistingCodeCategoryUUID03, #AlreadyExistingOldCodeCategoryName03
select count(*) from [dbo].[CodeCategoryDestinationTable] as CodeCategoryDestinationTableCOUNT
/* USP */
print '[uspCodeCategoryReplicateReplacer]'
go
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[uspCodeCategoryReplicateReplacer]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[uspCodeCategoryReplicateReplacer]
Go
/*
declare #numberRowsAffected int
declare #ErrorNumber int
exec [dbo].[uspCodeCategoryReplicateReplacer] #numberRowsAffected output , #ErrorNumber output
print #numberRowsAffected
print #ErrorNumber
print ''
*/
CREATE PROCEDURE [dbo].[uspCodeCategoryReplicateReplacer] (
#numberRowsAffected int output
,
#ErrorNumber int output
)
AS
SET NOCOUNT ON
select #ErrorNumber = 0
declare #ErrorTracker int
declare #insertRowCount int
declare #updateRowCount int
select #insertRowCount = 0
select #updateRowCount = 0
declare #CurrentInsertCount int
declare #ManualReplicationRowCount int
select #ManualReplicationRowCount = 333
declare #MaximumLoopCounter int
select #MaximumLoopCounter = 10000
while (#MaximumLoopCounter > 0) and exists
(
Select
TOP 1 null
from [dbo].[CodeCategorySourceTable] sourceTable with (nolock)
where not exists
(
select null from [dbo].[CodeCategoryDestinationTable] destinationTable with (nolock)
Where
destinationTable.CodeCategoryUUID = sourceTable.CodeCategoryUUID
)
)
BEGIN
select #MaximumLoopCounter = #MaximumLoopCounter - 1
/* DELETE FROM [dbo].[CodeCategoryDestinationTable] */
SET NOCOUNT OFF
Insert into [dbo].[CodeCategoryDestinationTable]
(
CodeCategoryUUID,
CodeCategoryName
)
Select
TOP (#ManualReplicationRowCount)
CodeCategoryUUID,
CodeCategoryName
from [dbo].[CodeCategorySourceTable] sourceTable with (nolock)
where not exists
(
select null from [dbo].[CodeCategoryDestinationTable] destinationTable with (nolock)
Where
destinationTable.CodeCategoryUUID = sourceTable.CodeCategoryUUID
)
SELECT #CurrentInsertCount = ##ROWCOUNT , #ErrorTracker = ##ERROR
select #insertRowCount = #insertRowCount + #CurrentInsertCount
if #ErrorTracker <> 0
BEGIN
select #ErrorNumber = #ErrorTracker
select #MaximumLoopCounter = 0 /*Bail Out !!!*/
END
SET NOCOUNT ON
END /*End While Loop*/
print '/Before Look [dbo].[CodeCategoryDestinationTable] */'
select * from [dbo].[CodeCategoryDestinationTable]
SET NOCOUNT OFF
/* A little extra. Update any non-surrogate-key values... We did not do this, but I leave it here as for kicks */
Update [dbo].[CodeCategoryDestinationTable]
Set
/*CodeCategoryUUID = vart.CodeCategoryUUID,*/
CodeCategoryName = sourceTable.CodeCategoryName
From
[dbo].[CodeCategoryDestinationTable] destinationTable, [dbo].[CodeCategorySourceTable] sourceTable
Where
/*Relationship*/
destinationTable.CodeCategoryUUID = sourceTable.CodeCategoryUUID
/*Filter*/
and destinationTable.CodeCategoryName <> sourceTable.CodeCategoryName
SELECT #updateRowCount = ##ROWCOUNT
SET NOCOUNT ON
print '/After Look [dbo].[CodeCategoryDestinationTable] */'
select * from [dbo].[CodeCategoryDestinationTable]
print '/#insertRowCount COUNT/'
print #insertRowCount
print '-------------------------'
print '/#updateRowCount COUNT/'
print #updateRowCount
print '-------------------------'
SELECT #numberRowsAffected = #insertRowCount + #updateRowCount
print '/ [dbo].[CodeCategoryDestinationTable] COUNT/'
print #numberRowsAffected
print '-------------------------'
SET NOCOUNT OFF
GO
/*GRANT EXECUTE ON dbo.uspCodeCategoryReplicateReplacer TO $(DBUSERNAME)*/
GO
/* Improvement , encapsulate the ManualReplicationRowCount "getter" so it can be changed in one place */
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[uspInternalSettingGetManualReplicationRowCount]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[uspInternalSettingGetManualReplicationRowCount]
GO
/*
--START TEST
declare #returnCode int
declare #ManualReplicationRowCount int
EXEC #returnCode = dbo.uspInternalSettingGetManualReplicationRowCount #ManualReplicationRowCount output
print #ManualReplicationRowCount
print '/#returnCode/'
print #returnCode
*/
CREATE PROCEDURE [dbo].[uspInternalSettingGetManualReplicationRowCount] (
#ManualReplicationRowCount int output --return
)
AS
SET NOCOUNT ON
select #ManualReplicationRowCount = 333
SET NOCOUNT OFF
GO
Here is my sql query.
CREATE FUNCTION UF_GetOrderProducts
(
#OrderId int
)
RETURNS VARCHAR(500)
AS
BEGIN
SELECT Identity(int,1,1) ID, ProductId INTO #Temp FROM OrderProduct WHERE OrderId = #OrderId
Declare #Id int,
#Count int,
#LoopCount int,
#ProductList VARCHAR(500),
#ProductListTemp VARCHAR(500)
SET #Count = (Select Count(*) From #Temp)
SET #LoopCount = 1
SET #ProductList = ''
WHILE #LoopCount <= #Count
BEGIN
SET #ProductListTemp =( SELECT Name FROM Product WHERE ProductId =(Select ProductId from #Temp Where ID = #LoopCount))
SET #ProductList +=#ProductListTemp + '<br/>'
Set #LoopCount=#LoopCount + 1
END
DROP TABLE #Temp
RETURN #ProductList
END
GO
I have to loop in #Temp Table. Do you have any other suggestions?
Instead of temp table you can use a table variable.
declare #Temp TABLE (ID int identity, ProductId int)
insert into #Temp(ProductId)
select ProductId
from OrderProduct
where OrderId = #OrderId
But you could rewrite your function without a loop.
Something like this should do what you want.
create function IF_GetOrderProducts
(
#OrderId int
)
returns varchar(500)
as
begin
return
(
select Name+'<br/>'
from Product as P
inner join OrderProduct as OP
on P.ProductId = OP.ProductId
where OP.OrderId = #OrderId
for xml path(''), type
).value('.', 'varchar(500)')
end