SqlServer Trigger to add multiple rows - sql-server

I have the following trigger:
ALTER TRIGGER .[dbo].[trgAfterInsertComment]
ON .[dbo].[Comment]
AFTER INSERT
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
declare #Id int;
declare #LoanId int;
declare #CopyId int;
declare #CustomerId int;
declare #Comment nvarchar(255);
--DECLARE cur CURSOR FOR
select #Id = Id from inserted
select #LoanId = LoanId from inserted
--select #CopyId = CopyId from deleted
--select #CustomerId = CustomerId from deleted
select #Comment = Comment from inserted
-- OPEN cur
--FETCH NEXT FROM cur INTO #Id, #ISBN, #Purchase_Date
--WHILE ##FETCH_STATUS = 0 BEGIN
-- your business logic
Declare #Title nvarchar(255);
select #Title = (Select Title from Book where ISBN = (select ISBN from copy where Id = (select CopyId from Loan where Id = #LoanId)))
select #CustomerId = (Select CustomerId from Loan where Id = #LoanId)
select #CopyId = (Select CopyId from Loan where Id = #LoanId)
insert into Activity("Heading", "Date")
values(Concat('New Comment added - Id: ', #Id, ' Title: ', #Title, ' Copy Id: ', #CopyId, ' Customer Id: ', #CustomerId, ' Comment: ', #Comment), GETDATE())
--FETCH NEXT FROM cur INTO #Id, #ISBN, #Purchase_Date
--END
--CLOSE cur
--DEALLOCATE cur
end
As you can see I have commented out a cursor that I was using to handle multiple inserts. Could someone tell me how I can handle multiple inserts without the cursor, as after reading around I see that using a cursor is a bad idea?
With the above trigger, if I try to insert multiple lines like this:
USE [Library]
GO
INSERT INTO [dbo].[Comment]
([LoanId]
,[Comment])
VALUES
(47, 'test'),
(48, 'test'),
(50, 'test')
GO
Only the first row is inserted into my Activity table. Thanks for any help

You need to shift it to be set based, using variables and a loop will cause you issues. Can't test the below, but something like:
INSERT INTO Activity
(
Heading ,
[Date]
)
SELECT CONCAT('New Comment added - Id: ', I.id, ' Title: ', COALESCE(B.Title,''), ' Copy Id: ', COALESCE(L.CopyID,''), ' Customer Id: ', COALESCE(L.CustomerID,'')) ,
GETDATE()
FROM inserted AS I
LEFT JOIN Loan AS L ON I.loanId = L.loanId
LEFT JOIN Copy AS C ON C.Id = L.CopyId
LEFT JOIN Book AS B ON B.ISBN = C.ISBN;

Do this querying inserted table directly.
insert into [dbo].[Comment] (LoanId, Comment)
select LoanId, Comment from inserted
You can change the select query to more complex to achieve the result using query only.

Related

Insert into tables based on updating list (table)

Ive been struggling with this one for a while and appreciate any help.
I have a table that continuously get updated with a list of table names (same table can occure several times) that has been updated with new data recently in Database 1.
I want to create a query that checks this update list and inserts the data from updated tables in Database 1, into corresponding tables in Database 2. And loops through until the end of the list.
The list can look like this:
ID Table TimeStamp
----------------------- -------- -----------------------
0313778E-CB68-E811-910D Customer 2018-07-10 13:27:28.567
0313778E-CB68-E811-910D Customer 2018-07-10 13:28:58.010
194DD17A-CE68-E811-910D Order 2018-07-10 13:27:28.567
0EBB391D-126B-E811-910D Product 2018-07-10 13:28:58.010
4AAE33A5-CE68-E811-910D Customer 2018-07-10 13:27:28.567
DFA2A68C-056B-E811-910D Order 2018-07-10 13:28:58.010
C2CFECB6-CE68-E811-910D Employee 2018-07-10 13:27:28.583
To make it worse, the tables in Database 2 don't have same amount of columns as Database 1.
Ive been working on both MERGE and Cursor, as well as dynamic SQL. Im new to these so keep getting stuck. I think dynamic SQL + CURSOR is the best way to go. All of this will result in a stored procedure. Maybe there is a better way of doing it? Anyway, this is what I have:
Declare #Source_TableName_Column --this one contains the Database 1 tables as well as the correct columns needed to fill matching table in Database 2.
Declare #InsertInto NVARCHAR(MAX),
#TargetTable NVARCHAR(MAX)='Select name from Database2.sys.all_objects', --list of tables I have in Database 2
#Columns NVARCHAR(MAX) = 'Select name from Database2.sys.all_columns', --list of columns I have in Database 2 (same names as it is in SourceTable in Database 1)
;
DECLARE TableInsert CURSOR FOR
SELECT distinct SourceTableName from Database3.dbo.UpdateTableList
OPEN TableInsert
FETCH NEXT FROM TableInsert
INTO #TableName
--LOOP
WHILE ##FETCH_STATUS=0
BEGIN
SET #InsertInto = 'insert into Database2.dbo.'+#TargetTable+' '+(#Columns)+' values'+(....)+'' --not sure how to do this variable where i get all the results from SourceTable matching columns in TargetTable in database 2
FETCH NEXT FROM TableInsert
INTO #TableName
END
--CLOSE CURSOR
CLOSE TableInsert
DEALLOCATE TableInsert
This is complex. I would approach it in a simpler fashion than what you are doing. I’d do it your way if scenario involved destination tables with the same schema, but numerous columns, which does not seem to be the case with you.
Here’s what i’d do.
Open cur1
Fetch next from cur1 into #tablename ....
While ##fetchstatus = 0
Begin
If ##tablename= ‘tbl1’
Begin
Insert into database2.dbo.tbl2 values
Select ... from database1.dbo.table1 where ..
End
If ##tablename = ‘tblx’
And so on
Fetch next from cur1 into ...
End
I made a solution that works for me. Some names I have changed here to better fit my description above. I think they are correct, will look through it later and correct it if wrong =)
I am, however, a bit unsure about the delete statement further down in the code.
I have a TempTable based on the update list. I want to delete the rows in the update list after Ive inserted into tables. I have one with two 'where field IN (corresponding field in TempTable' clauses and another one with a 'delete from ... where exists (tempTable). Temptable has two columns but update list has three in total. Whichever is fastest/best?
DECLARE #InsertInto NVARCHAR(MAX);
DECLARE #SourceID NVARCHAR(MAX);
DECLARE #TableAttribute NVARCHAR(MAX);
DECLARE #SourceViewName NVARCHAR(MAX);
DECLARE #TargetTable NVARCHAR(MAX);
DECLARE #SourceTableName NVARCHAR(MAX);
/*-------Create temp table to be used in cursor-------*/
Declare #SQL_TempTable_Insert NVARCHAR(MAX);
IF OBJECT_ID('tempdb..#Cursor_TempTable') IS NOT NULL DROP TABLE #Cursor_TempTable
CREATE TABLE #Cursor_TempTable (
SourceEntity NVARCHAR(MAX) )
/*-------variable to be used in insert step below-------*/
SET #SQL_TempTable_Insert = 'SELECT SourceLogicalName FROM DataBaseC.dbo.REF_ENTITIES_SYNC group by SourceLogicalName'
/*-------Insert into temp table-------*/
INSERT INTO #Cursor_TempTable EXECUTE (#SQL_TempTable_Insert)
/*-------Create temp table from NeworUpdate table-------*/
Declare #SQL_TempTable_NewOrUpdated NVARCHAR(MAX);
IF OBJECT_ID('tempdb.. #TempTable_NewOrUpdated') IS NOT NULL DROP TABLE #TempTable_NewOrUpdated
CREATE TABLE #TempTable_NewOrUpdated (
[ID] NVARCHAR(MAX),
[TimeStamp] DATETIME )
/*-------variable to be used in insert step below in NewOrUpdate temp table-------*/
SET #SQL_TempTable_NewOrUpdated = 'SELECT ID, TimeStamp FROM DataBaseC.dbo.[REF_POSTS_NewOrUpdated] group by ID, TimeStamp'
/*-------Insert into NewOrUpdate temp table-------*/
INSERT INTO #TempTable_NewOrUpdated EXECUTE (#SQL_TempTable_NewOrUpdated)
/*-------Cursor segment-------*/
DECLARE EntitiesInsert CURSOR FOR
SELECT SourceEntity FROM #Cursor_TempTable
OPEN EntitiesInsert
FETCH NEXT FROM EntitiesInsert
INTO #TargetTable
--LOOP
WHILE ##FETCH_STATUS=0
BEGIN
BEGIN TRY
BEGIN TRAN
SET #SourceViewName = (select SourceName from DataBaseC.dbo.REF_ENTITIES_SYNC where Targetname = #TargetTable);
SET #SourceTableName = (select SourceTableName from DataBaseC.dbo.REF_ENTITIES_SYNC where Targetname = #TargetTable);
SET #TableAttribute = stuff(( select ', ' +char(10)+ ac.[name] from DataBaseB.sys.all_columns ac
inner join DataBaseB.sys.all_objects ao on ao.object_id=ac.object_id
where ao.name = #TargetTable and ac.name not in ('ValidFrom','ValidTo')
FOR XML PATH('')
), 1, 1, '')
--Finds DatabaseA table's Primary Key
SET #SourceID = (select c.name
from sys.index_columns ic
inner join sys.columns c on ic.object_id = c.object_id and ic.column_id = c.column_id
inner join sys.indexes i on ic.object_id = i.object_id and ic.index_id = i.index_id
inner join sys.tables t on i.object_id = t.object_id
inner join sys.schemas s on t.schema_id = s.schema_id
where i.is_primary_key= 1 and t.name = #SourceTableName);
SET #InsertInto = 'INSERT INTO DataBaseB.dbo.'+#TargetTable+' ('+#TableAttribute+')
SELECT '+#TableAttribute+' FROM DataBaseA.dbo.'+#SourceViewName+'
where '+#SourceID+' in (select nu.ID from DataBaseC.Inno.REF_ENTITIES_SYNC sync inner join #TempTable_NewOrUpdated nu on nu.SourceEntity = sync.TargetName where sync.TargetName = '''+#TargetTable+''' group by nu.ID )'
EXEC sp_sqlexec #insertInto
--Delete the records from [DataBaseC].[dbo].[REF_POSTS_NewOrUpdated] that we have inserted.
--DELETE FROM [DataBaseC].[dbo].[REF_POSTS_NewOrUpdated]
-- WHERE ID = (select [ID] from #TempTable_NewOrUpdated)
-- AND TimeStamp = (select [Timestamp] from #TempTable_NewOrUpdated)
----alt2
--DELETE FROM [DataBaseC].[dbo].[REF_POSTS_NewOrUpdated]
-- where exists (select * from #TempTable_NewOrUpdated)
--End TRAN
COMMIT
--End TRY
END TRY
--Catch possible errors
BEGIN CATCH
--IF there is an open transaction then roll back and print error messages.
IF ##TRANCOUNT > 0
ROLLBACK TRANSACTION
DECLARE #ErrorNumber INT = ERROR_NUMBER();
DECLARE #ErrorLine INT = ERROR_LINE();
DECLARE #ErrorMessage NVARCHAR(4000) = ERROR_MESSAGE();
DECLARE #ErrorSeverity INT = ERROR_SEVERITY();
DECLARE #ErrorState INT = ERROR_STATE();
PRINT 'Actual error number: ' + CAST(#ErrorNumber AS VARCHAR(10));
PRINT 'Actual line number: ' + CAST(#ErrorLine AS VARCHAR(10));
PRINT 'Actual error message: ' + CAST(#ErrorMessage AS VARCHAR(MAX));
PRINT 'Actual error Severity: ' + CAST(#ErrorSeverity AS VARCHAR(MAX));
PRINT 'Actual error State: ' + CAST(#ErrorState AS VARCHAR(MAX));
END CATCH
FETCH NEXT FROM EntitiesInsert
INTO #TargetTable
END
CLOSE EntitiesInsert
DEALLOCATE EntitiesInsert
GO

Convert stored procedure which uses exec to populate table to scalar-valued function

I have this stored procedure:
ALTER procedure [dbo].[sp_checker2]
(#Item varchar(70), #location varchar(8))
as
declare #Query varchar(2000)
set #location = 'XXX909'
declare #Table Table (Qty int)
set #Query = 'select TOP 1 * from openquery(xxxx,''SELECT NVL(b.t$st,0) from server.XXXXXID0001 a left join
server.XXXXXID0002 b on a.t$item = b.t$item where b.t$cloc = '''''+ #location + ''''' and trim(a.t$item)='''''+ #Item + ''''''')'
insert into #Table exec (#Query)
if not exists (select * from #Table )
begin
set #Query = 'select TOP 1 * from openquery(xxxx,''SELECT NVL(b.t$st,0) from server.XXXXXID0001 a
left join server.XXXXXID0002 b on a.t$item = b.t$item where trim(a.t$item) = '''''+ #Item + ''''''' )'
insert into #Table exec (#Query)
end
select * from #Table
The thing is I am looking to a query SELECT like this:
SELECT
column1, column2, column3, column4,
(EXEC [dbo].[sp_checker2] 'param1=value of column3', 'param2=another value') AS column5
FROM
table
WHERE
column1 = 'data1'
AND column2 = 'data2'
ORDER BY
column3
I know it is not possible to execute a stored procedure in a SELECT statement in SQL Server and the alternative I have is to convert the stored procedure to a function, but inside the stored procedure I have an exec to insert data into the table variable. Is there a way I can convert this stored procedure to a function ?
P.S. I only save one row in the variable table, ie: if item exists it saves its inventory: "6500"
It is difficult. In a function it is not possible to execute dynamic SQL. I think it is only possible if the WHERE criteria are shifted. You'll be better able to evaluate what impact this has on the performance.
CREATE FUNCTION [dbo].[f_checker2] (#item varchar(70),
#location varchar(8))
RETURNS #result TABLE (
Qty int
)
AS
BEGIN
INSERT
INTO #result
select TOP(1) qty
from openquery(xxxx, 'SELECT NVL(b.t$st,0) AS qty,
b.t$cloc AS location,
trim(a.t$item) AS item
from server.XXXXXID0001 a
left join server.XXXXXID0002 b
on a.t$item = b.t$item')
where location = #location
and item = #item
if not exists (select * from #result)
INSERT
INTO #result
select TOP(1) qty
from openquery(xxxx, 'SELECT NVL(b.t$st,0) AS qty,
b.t$cloc AS location,
trim(a.t$item) AS item
from server.XXXXXID0001 a
left join server.XXXXXID0002 b
on a.t$item = b.t$item')
where item = #item
RETURN
END
GO

Advanece SQL Update query

Question:
Want to update Inflow by checking the condition what is the value we have under inflow column in reporting table
e.g if we have a CASE WHEN FLAG = '1' THEN 'AS' ELSE 'LI' it should check the value for flag column if it is 1 then value should be 'AS' else 'L1'
Note: INFLOW column under reporting have different values.
Table Structure:
create table dummy ( ID VARCHAR(10), PRODUCT VARCHAR(10), INFLOW VARCHAR(10) );
INSERT INTO dummy(ID,PRODUCT) VALUES('10','999')
INSERT INTO dummy(ID,PRODUCT) VALUES('11','888')
INSERT INTO dummy(ID,PRODUCT) VALUES('12','111')
INSERT INTO dummy(ID,PRODUCT) VALUES('13','222')
create table REPORTING_FLAG
(
ID VARCHAR(10),
PRODUCT VARCHAR(10),
INFLOW VARCHAR(2000),
FLAG VARCHAR(10),
L3 VARCHAR(10)
);
INSERT INTO REPORTING VALUES('10','999','CASE WHEN FLAG = ''1'' THEN ''AS'' ELSE ''LI''','1','SALR')
INSERT INTO REPORTING VALUES('11','888','CASE WHEN L3 = ''SALR'' THEN ''SALR'' ELSE ''OTHR''','1','XYZ')
INSERT INTO REPORTING VALUES('12','111','ABC','2','PQR')
INSERT INTO REPORTING VALUES('13','222','SAP','3','QWE')
When performing larger inserts, it is wise and correctly-applied logic to perform transformation on the sets of data, rather than each individual row.
Even if this is unavoidable, do not make the mistake of being comfortable with myriads of update/insert statements,which not only costs resources but trashes statistics, fragments your indexes and drives alike.
Run a SELECT statement that uses a CASE logic and verify the results. Once you can safely perform this on the select statement, convert it to an Update statement (note your update can use joins)
This should work
declare dummyproducts cursor for select ID, Product, Inflow from reporting
declare #ID VARCHAR(10), #PRODUCT VARCHAR(10), #INFLOW VARCHAR(2000)
OPEN dummyproducts
Fetch next from dummyProducts into #ID, #PRODUCT, #INFLOW
while ##fetch_Status = 0
BEGIN
declare #sql nvarchar(max)
if CHARINDEX('CASE', #INFLOW) > 0
set #Inflow = #inflow + ' end'
else
set #inflow = 'r.inflow'
set #sql = 'Update dummy set INFLOW = ' +
#INFLOW
+ ' from
reporting r inner join dummy d on r.Product = d.Product and r.ID = d.ID where d.ID = ' + #ID + ' and d.Product = ' + #Product
print #sql
exec (#sql)
Fetch next from dummyProducts into #ID, #PRODUCT, #INFLOW
END
close dummyProducts
deallocate dummyProducts
GO

SQL Server How to output one table result from multiple results with a WHILE query

From this answer: Is there a way to loop through a table variable in TSQL without using a cursor?
I'm using the method
WHILE EXISTS(SELECT * FROM #Temp)
The problem is that it's outputting multiple tables, if possible I'd like to output as a single table.
Declare #Id int
WHILE EXISTS(SELECT * FROM #Temp)
Begin
Select Top 1 #Id = Id From #Temp
--Do some processing here
Delete #Temp Where Id = #Id
End
So right now it outputs this:
x y
-- --
1 a
x y
-- --
1 b
But I'd like it to output this:
x y
-- --
1 a
2 b
What I'm trying to achieve, I have this in a field:
1234,1432,1235
I have a process that splits the field into records(it works with sql server 2000):
DECLARE #String VARCHAR(100)
SELECT #String = str FROM field --with the 1234,1432,1235
SELECT SUBSTRING(',' + #String + ',', Number + 1,
CHARINDEX(',', ',' + #String + ',', Number + 1) - Number -1)AS str
INTO #temp
FROM master..spt_values
WHERE Type = 'P'
AND Number <= LEN(',' + #String + ',') - 1
AND SUBSTRING(',' + #String + ',', Number, 1) = ','
GO
So now, #temp has:
str
---
1234
1432
1235
So I need to go through each record to query the information I need.
And I'd like it to output something like this:
str name age
--- ---- ---
1234 Bob 23
1432 Jay 41
1235 Tim 12
The current While loop outputs it like this, which I don't want:
str name age
--- ---- ---
1234 Bob 23
str name age
--- ---- ---
1432 Jay 41
str name age
--- ---- ---
1235 Tim 12
Final Working Result:
SET NOCOUNT ON;
DECLARE #String VARCHAR(1000);
SELECT #String = Tnn FROM (SELECT
CO.USER_2 AS Tnn
FROM
[VMFG].[dbo].[CUSTOMER_ORDER] AS CO
LEFT JOIN DBO.Tnn_Header AS Tnn ON Tnn.TnnNumber = CO.USER_2 AND Tnn.StatusID = '5' WHERE CO.ID = 'ORDERID') AS Place --with the 1234,1432,1235
DECLARE #Id nvarchar(50),
#Discount nvarchar(50),
#Spin nvarchar(50),
#Commission_Hmm nvarchar(50),
#Commission nvarchar(50),
#TnnID nvarchar(50);
DECLARE #Output TABLE (
TnnNumber nvarchar(50),
Discount nvarchar(50),
Spin nvarchar(50),
Commission_Hmm nvarchar(50),
Commission nvarchar(50),
TnnID nvarchar(50));
DECLARE crs CURSOR STATIC LOCAL READ_ONLY FORWARD_ONLY
FOR SELECT SUBSTRING(',' + #String + ',', Number + 1,
CHARINDEX(',', ',' + #String + ',', Number + 1) - Number -1) AS [ID]
FROM master..spt_values
WHERE Type = 'P'
AND Number <= LEN(',' + #String + ',') - 1
AND SUBSTRING(',' + #String + ',', Number, 1) = ',';
OPEN crs;
FETCH NEXT
FROM crs
INTO #Id;
WHILE (##FETCH_STATUS = 0)
BEGIN
-- do some processing..
SELECT
#Id = TH.TnnNumber,
#Discount = CASE WHEN COUNT(DISTINCT TL.DiscountCodeID) > 1 THEN 'Varies, View Tnn' ELSE CAST(MAX(DC.Value) AS VARCHAR(60)) END,
#Spin = CASE WHEN TS.SpinID > 4 THEN 'Has Specifics, View Tnn' ELSE TS.Value END,
#Commission_Hmm = CASE WHEN COUNT(DISTINCT TL.Commission_Hmm) > 1 THEN 'Varies, View Tnn' ELSE CAST(MAX( ISNULL(str(TL.Commission_Hmm,12),'Default Comm')) AS VARCHAR(60)) END,
#Commission = CASE WHEN COUNT(DISTINCT TL.Commission) > 1 THEN 'Varies, View Tnn' ELSE CAST(MAX(ISNULL(str(TL.Commission,12),'Default Comm')) AS VARCHAR(60)) END,
#TnnID = TL.TnnID
FROM DBO.Tnn_Header AS TH
LEFT JOIN DBO.Tnn_LINE AS TL ON TH.TnnID = TL.TnnID
LEFT JOIN DBO.Tnn_Spin AS TS ON TH.SpinID = TS.SpinID
LEFT JOIN DBO.Tnn_DiscountCode AS DC ON TL.DiscountCodeID = DC.DiscountCodeID
WHERE TnnNumber = #id
GROUP BY
TH.TnnNumber,
TS.SpinID,
TS.Value,
TL.TnnID
-- end do some processing..
INSERT INTO #Output (TnnNumber, Discount, Spin, Commission_Hmm, Commission, TnnID)
VALUES (#Id, #Discount, #Spin, #Commission_Hmm, #Commission, #TnnID);
FETCH NEXT
FROM crs
INTO #Id;
END;
CLOSE crs;
DEALLOCATE crs;
SELECT TnnNumber, Discount, Spin, Commission_Hmm, Commission, TnnID
FROM #Output;
You are wasting your time and energy following such bad advice. If you absolutely must (extra emphasis on the must) take a row-by-row approach (CURSOR or WHILE loop), then you are better off with a CURSOR. It is a built-in construct that is more efficient, and less error-prone. You just need to use the right options, such as making it STATIC, LOCAL, READ_ONLY, and FORWARD_ONLY. You don't need STATIC if the cursor query is only hitting temporary tables and/or table variables.
People will argue with this and say that "you must avoid cursors at all cost!", but they haven't done the tests to see that such a popular notion is really just a myth. And if they have done tests that appear to confirm it, then they haven't set the appropriate options, mostly STATIC, which dumps the result of the cursor query into a temp table. Without this option, fetching new rows will re-check the base tables to make sure that they still exist, and that is where the performance hit is (the I/O plus the locking). And that is also why you typically don't need the STATIC option when querying only temporary tables and/or table variables. What do I mean by "re-checking"? Just look at the documentation for ##FETCH_STATUS. The return values don't just cover "success" (0) and "no more rows" (-1): there is a return value, (-2), that means "The row fetched is missing".
SET NOCOUNT ON;
DECLARE #Id INT,
#Name sysname,
#Type VARCHAR(5);
-- the Table Variable replaces #Temp2 in the original query
DECLARE #Output TABLE (Id INT NOT NULL, Name sysname, [Type] VARCHAR(5));
-- the CURSOR replaces #Temp in the original query
DECLARE crs CURSOR STATIC LOCAL READ_ONLY FORWARD_ONLY
FOR SELECT [object_id], name, [type]
FROM sys.objects -- dbo.sysobjects for SQL 2000 -- ATable in the original query
ORDER BY [object_id] ASC;
OPEN crs;
FETCH NEXT
FROM crs
INTO #Id, #Name, #Type;
WHILE (##FETCH_STATUS = 0)
BEGIN
INSERT INTO #Output (Id, Name, [Type])
VALUES (#Id, #Name, #Type);
-- do some processing..
FETCH NEXT -- replaces the DELETE and re-SELECT in the original query
FROM crs
INTO #Id, #Name, #Type;
END;
CLOSE crs;
DEALLOCATE crs;
SELECT Id, Name, [Type]
FROM #Output;
UPDATE
Given the iteration is being done over a query that splits a CSV of INTs, the resulting query would look similar to the following:
SET NOCOUNT ON;
DECLARE #String VARCHAR(1000);
SELECT #String = str FROM [Table]; --with the 1234,1432,1235
DECLARE #Id INT,
#Name NVARCHAR(50),
#Age TINYINT;
DECLARE #Output TABLE (Id INT NOT NULL, Name NVARCHAR(50), Age TINYINT);
DECLARE crs CURSOR STATIC LOCAL READ_ONLY FORWARD_ONLY
FOR SELECT SUBSTRING(',' + #String + ',', Number + 1,
CHARINDEX(',', ',' + #String + ',', Number + 1) - Number -1) AS [ID]
FROM master..spt_values
WHERE Type = 'P'
AND Number <= LEN(',' + #String + ',') - 1
AND SUBSTRING(',' + #String + ',', Number, 1) = ',';
OPEN crs;
FETCH NEXT
FROM crs
INTO #Id;
WHILE (##FETCH_STATUS = 0)
BEGIN
-- do some processing..
-- Logic to set value of #Name
-- Logic to set value of #Age
INSERT INTO #Output (Id, Name, Age)
VALUES (#Id, #Name, #Age);
FETCH NEXT
FROM crs
INTO #Id;
END;
CLOSE crs;
DEALLOCATE crs;
SELECT Id, Name, Age
FROM #Output;
your query has syntax error but I tried below query and worked fine
-- this is only to populate my data table
Select object_id Id, name Into #Temp From sys.tables
select * into #temp2 from #Temp where 1=2
Declare #Id int
WHILE EXISTS(SELECT * FROM #Temp)
Begin
Select Top 1 #Id = Id
From #Temp
ORDER BY Id -- this order is important
-- use insert...into, NOT select...into
insert into #temp2
select *
from #Temp
where Id = #Id
Delete #Temp Where Id = #Id
End
BTW, you can not have SELECT...INTO inside a loop, as the 2nd iteration will raise error.
You need to create #temp2, out side the loop and use INSERT...INTO instead of SELECT...INTO

select query returns empty in sp but when run it alone, it is not empty. Why?

I have a stored procedure that I write to Table and read table. I write with no problem but when I want to read it returns empty. but it is not empty when I select query and run it returns data. Why it can be.
Here is my codes. I give fulltext index Dump and TempTable to tag,title and body columns.
IF LEFT(#splitdata,1) = '#'
BEGIN
SET #splitdata = (SELECT REPLACE(#splitdata,'#',''))
INSERT INTO [WebTR].[dbo].[TempTable]
SELECT p.*
FROM [WebTR].[dbo].[Dump] AS p
INNER JOIN containstable([WebTR].[dbo].[Dump], tags, #splitdata) AS k
ON p.dumpID = k.[key]
end
SET #replacedLast += #replaced2
FETCH NEXT FROM TableA_cursor INTO #row
I insert temptable first then
IF EXISTS(SELECT * FROM WebTR.dbo.TempTable)
BEGIN
SELECT #replacedLast AS withtag
select dumpId,title,source,tags,creationdate,status,body,createdBy,max(rank) as rank,'olsanaaa' AS sinir
from
((SELECT p.*, k.rank
FROM WebTR.dbo.TempTable AS p
INNER JOIN containstable(WebTR.dbo.TempTable, title,'"*cunku*"' ) AS k
ON p.dumpID = k.[key]
)
union
(
SELECT p.*, k.rank
FROM WebTR.dbo.TempTable AS p
INNER JOIN containstable(WebTR.dbo.TempTable, body, '"*cunku*"') AS k
ON p.dumpID = k.[key]
))y group by dumpId,title,source,tags,creationdate,status,body,createdBy
order by rank DESC
END
as you can see in that if block when I select only select query it returns data but when execute stored procedure it returns empty even it enters the if block
here is he full sp:
USE [WebTR]
GO
/****** Object: StoredProcedure [dbo].[search] Script Date: 10.6.2015 16:19:25 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <Author,,Name>
-- Create date: <Create Date,,>
-- Description: <Description,,>
-- =============================================
ALTER PROCEDURE [dbo].[search]
#param1 varchar(250)
AS
BEGIN
declare #searchString varchar(250)
set #searchString = LTrim(RTrim(#param1))
TRUNCATE TABLE [WebTR].[dbo].[TempTable]
--SELECT ROW_NUMBER() OVER(ORDER BY #param1 ASC) AS row , * INTO #temp1 from WebTR.dbo.fnsplitstring(#searchString ,'')
SELECT ROW_NUMBER() OVER(ORDER BY CAST(SUBSTRING(splitdata, 0, 2) AS CHAR(1)) desc) AS row,* INTO #params from WebTR.dbo.fnsplitstring(#searchString ,'')
SET NOCOUNT ON
DECLARE #row INT
DECLARE #splitdata VARCHAR(50)
DECLARE #replaced1 VARCHAR(500)
DECLARE #replaced2 VARCHAR(500)
DECLARE #replacedLast VARCHAR(500)
DECLARE #last VARCHAR(500)
DECLARE TableA_cursor CURSOR FOR SELECT row FROM #params
SET #last = (SELECT COUNT(*) FROM #params)
SET #replacedLast = ''
OPEN TableA_cursor
FETCH NEXT FROM TableA_cursor INTO #row
WHILE ##FETCH_STATUS = 0
BEGIN
SET #splitdata = (SELECT splitdata FROM #params WHERE row=#row)
IF LEFT(#splitdata,1) = '#'
BEGIN
SET #splitdata = (SELECT REPLACE(#splitdata,'#',''))
BEGIN TRANSACTION
INSERT INTO [WebTR].[dbo].[TempTable]
SELECT p.*
FROM [WebTR].[dbo].[Dump] AS p
INNER JOIN containstable([WebTR].[dbo].[Dump], tags, #splitdata) AS k
ON p.dumpID = k.[key]
COMMIT TRANSACTION
end
ELSE
begin
IF LEFT(#splitdata,1)='-'
BEGIN
IF RIGHT(#replacedLast,4) = 'AND '
BEGIN
SET #replaced1 =('NOT ')
END
ELSE
BEGIN
SET
#replaced1 =('NOT ')
end
SET #replaced2= #replaced1 + (SELECT REPLACE (#splitdata, '-', '"*'))
SET #replaced2= #replaced2 + '*" ' + 'AND '
END
ELSE
BEGIN
SET #replaced2 =('"*')
SET #replaced2 = #replaced2 + (SELECT #splitdata + '*" AND ')
END
SET #replacedLast += #replaced2
END
FETCH NEXT FROM TableA_cursor INTO #row
IF ##FETCH_STATUS !=0
BEGIN
IF RIGHT(#replacedLast,4)='AND '
BEGIN
SET #replacedLast =LEFT(#replacedLast,(LEN(#replacedLast)-3))
END
END
END
CLOSE TableA_cursor
DEALLOCATE TableA_cursor
IF EXISTS(SELECT * FROM WebTR.dbo.TempTable)
BEGIN
SELECT #replacedLast AS withtag
select dumpId,title,source,tags,creationdate,status,body,createdBy,max(rank) as rank,'olsanaaa' AS sinir
from
((SELECT p.*, k.rank
FROM WebTR.dbo.TempTable AS p
INNER JOIN containstable(WebTR.dbo.TempTable, title,'"*cunku*"' ) AS k
ON p.dumpID = k.[key]
)
union
(
SELECT p.*, k.rank
FROM WebTR.dbo.TempTable AS p
INNER JOIN containstable(WebTR.dbo.TempTable, body, '"*cunku*"') AS k
ON p.dumpID = k.[key]
))y group by dumpId,title,source,tags,creationdate,status,body,createdBy
order by rank DESC
END
ELSE
BEGIN
select * into #temp1
from
((SELECT p.*, k.rank
FROM [WebTR].[dbo].[Dump] AS p
INNER JOIN containstable([WebTR].[dbo].[Dump], title, #replacedLast) AS k
ON p.dumpID = k.[key]
)
union
(
SELECT p.*, k.rank
FROM [WebTR].[dbo].[Dump] AS p
INNER JOIN containstable([WebTR].[dbo].[Dump], body, #replacedLast) AS k
ON p.dumpID = k.[key]
))x
select dumpId,title,source,tags,creationdate,status,body,createdBy,max(rank) as rank
from #temp1 with (NOLOCK)
group by dumpId,title,source,tags,creationdate,status,body,createdBy
order by rank DESC
DROP TABLE #temp1
end
END
CLOSE TableA_cursor
DEALLOCATE TableA_cursor
did you checked this part ? Because your cursor is closing before some actions.
I have this misbehaviour in SQL Server 2008 too. If you insert and retrieve too fast with fulltext index your query won't result in the new queries.
Maybe you need a manual population of your fulltext index.
See example based on AdventureWorks
ALTER FULLTEXT INDEX ON HumanResources.JobCandidate START UPDATE POPULATION;
GO
https://technet.microsoft.com/en-us/library/ms142575.aspx
Hopefully the Population update will fix your issue.
Best regards,
Ionic

Resources