I have created an stored procedure in SQL Server 2008 and it contains the following code snippet:
WHILE (#COUNTER <= #COUNT_ROWSTOBEPROCESSED )
BEGIN
DECLARE #INFID AS INT =0;
DECLARE #TPID AS INT =0;
SELECT #INFID = InfID FROM #TEMPTABLE WHERE ##ROWCOUNT = #COUNTER;
print #INFID ;
SET #COUNTER = #COUNTER + 1;
END
But it gives me following result:
(106 row(s) affected)
0
-26
0
0
0
0
0
0
0
0 all are zeros ....
I have already values in the temp table but it is not initialized into #INFID variable.
Why it is happening? I don't understand...
Please help me, if anyone have a solution.
----Comment---
yeap, I have seen into my code. But here I have already added counter increment in my code. but still i have same problem.
when i have run the below query inside the loop. i found that ##RowCount is always 1.
SELECT InfID,#ROWCOUNT FROM #TEMPTABLE WHERE ##ROWCOUNT = #COUNTER;
Can u tell me how to iterate each row of temptable using while loop or for loop in sql?
WHERE ##ROWCOUNT = #COUNTER is incorrect.
##ROWCOUNT returns the number of rows affected by the previous statement.
It will only evaluate to true once. (When #COUNTER = 1) so the rest of the time no assignment is made to #INFID from the SELECT operation.
What are you trying to do? My best guess is that you need to add an IDENTITY column to your table and reference that instead of ##ROWCOUNT or use a cursor.
But if you explain your end goal we may be able to tell you a set based way of achieving whatever your goal is without RBAR processing.
Related
I am trying to insert data from one table into another (from table [PPRS] to table [Verify]) where the Caption in PPRS is the same as in table [Master]. Someone suggested i use a loop to insert the data instead of hard coding it, however I am confused as to how to go about it.
Here's my code so far:
Declare #counter int
declare #total int
set #counter = 0
SELECT #total = Count(*) FROM PPRS
while #counter <= #total
begin
set #counter += 1
insert into [Verify]
select [Task_ID],
[Project_StartDate] ,
[PPR_Caption],
[Date]
FROM PPRS
where [PPR_Caption] in (SELECT [Caption] from Master)
end
No data is being inserted (0 rows affected)
The sample data I'm trying to insert:
17286 01/03/2018 MP - Youth Environmental Services (12/15) 15/10/2018
I suggest that this is along the lines of what you want to do:
INSERT INTO [Verify] (some_col) -- you never told us the name of this column
SELECT TOP 10 [PPR_Caption]
FROM PPRS
WHERE [PPR_Caption] IN (SELECT [Caption] FROM MasterRecords)
ORDER BY some_column;
That is, you want to insert ten records into the Verify table, determined by some order in the source PPRS table.
Try to declare specific columns to which you want to make insert. Please provide definition of table PPRS and Verify for more precise help from community.
Anyway idea please find bellow:
Declare #counter int
set #counter = 0
while #counter <= 10
begin
set #counter += 1
insert into [Verify] (NameofColumn1_Table_Verify, NameofColumn2_Table_Verify,...)
select PPRS.NameofColumn1_Table_PPRS,
PPRS.NameofColumn2_Table_PPRS,
...
FROM PPRS
where PPRS.[PPR_Caption] in (SELECT DISTINCT [Caption] from MasterRecords)
end
Anyway I think the loop is unnecesary. One batch should make it. Please write what you want to achieve at the end.
I have been looking for an answer to this question, but I believe it may be a useful piece of information for others as well.
I am working with TSQL in SQL server management studio. Due to the way our system processes information, it's desirable to do updates in smaller batches. A trick we use is to wrap updates in a while loop as such:
while (##Rowcount <> 0)
begin
update top (800) etc etc
end
I have created a job to do this update regularly and while this works in a query window, it does not seem to work in a job. Is the rowcount value populated when a job begins?
##ROWCOUNT is 0 at the beginning of a statement, what is happening for you is that when SSMS first opens up a connection it executes a series of queries behind the scenes (you can capture the specific queries with a trace), so you get a residual value for ##ROWCOUNT of 1.
When doing batch updates like this, I tend to take a slightly different approach:
WHILE 1 = 1
BEGIN
UPDATE TOP (100) ....
SET ...
IF ##ROWCOUNT = 0
BREAK;
END
I don't think this has any benefit whatsoever over doing something like:
SELECT 1;
WHILE ##ROWCOUNT > 0
BEGIN
...
END
And is more long winded, but doing a pointless select or assignment just feels odd to me, perhaps owing to some minor OCD.
##Rowcount is system function with output INT NOT NULL --> default value for int is 0
You can get it by:
if ##rowcount = 0
print 1
else
print 0
But don't try select ##rowcount at first row it's statements that make a simple assignment and is always set the ##ROWCOUNT value to 1. :)
So solution is add select 0 before your while. It works because ##rowcount of select 0 is one row..
select 0
while (##Rowcount <> 0)
begin
update top (800) etc etc
end
Saving the value of ##RowCount in a variable allows you to avoid any assumption about the initial value and any problems with losing the value when another statement is executed.
declare #Samples as Table ( Sample Int );
insert into #Samples ( Sample ) values ( 1 ), ( 2 ), ( 5 );
declare #RowCount as Int;
-- If there is any work to do then initialize #RowCount to 1 , otherwise 0 .
set #RowCount = case when exists ( select 42 from #Samples where Sample < 10 ) then 1 else 0 end;
declare #NewSample as Int, #OldSample as Int;
-- Loop through updating one row at a time.
while #RowCount > 0
begin
update Ph
set #OldSample = Sample, #NewSample = Sample *= 2
from ( select top 1 Sample from #Samples where Sample < 10 order by Sample ) as Ph
set #RowCount = ##RowCount;
-- Do what you will without losing the count of rows updated.
select #RowCount as 'RowsProcessed', #OldSample as 'OldSample', #NewSample as 'NewSample'
end
I have a table name resultado, that is created by calling and executing another stored procedures or functions. As a result a have a column that contains '1' and '0' as a vector like this '111100001'. Also I have a store procedured that count the numbers of 1 in the 'vector' as it follows.
ALTER PROC [dbo].[CharCount](#String VARCHAR(4000),#caracter VARCHAR(2))
AS
BEGIN
DECLARE #long INT
DECLARE #numeroveces INT =0
DECLARE #consecutivo INT =0
DECLARE #consecutivo1 INT =0
SET #numeroveces=0
SET #long=LEN(#String)
WHILE #long>=0
BEGIN
IF #caracter=SUBSTRING(#String,#long,1)
BEGIN
set #numeroveces = #numeroveces + 1
set #consecutivo = #consecutivo + 1
END
IF #caracter<>SUBSTRING(#String,#long,1) or (#long = 0)
BEGIN
IF #consecutivo > #consecutivo1
BEGIN
set #consecutivo1 = #consecutivo
END
set #consecutivo = 0
END
SET #long=#long-1
END
SELECT #numeroveces
SELECT #consecutivo1
END
What I need is to execute the store procedure over a column from my table resultado and update the column with the result of the SP.
OriginalColumn--->SPResult---->UpdatedColumn
110111 ---> 5 ----> 5
Your procedure has 2 result sets the way you have it coded. Since in the example you posted here you are only trying to get the count of a given character I would strongly advise you to not use this procedure. It is horribly inefficient for such a simple task. This simple code will get the number of occurrences of a character without doing any looping. If you also need the longest consecutive count of occurrences there are better ways to do that too.
declare #String varchar(4000) = '111100001'
, #caracter VARCHAR(2) = '1'
select LEN(#String) - LEN(Replace(#String, #caracter, ''))
I have to check if some records with specific conditions exist in a table which may not exist and I must do this in a scalar function.
Here is my code:
CREATE FUNCTION CheckIfRecordsExistInTestTable()
RETURNS INT
BEGIN
DECLARE #Result INT
SELECT #Result =
CASE WHEN OBJECT_ID('TestTable') IS NULL THEN 0
ELSE
CASE WHEN EXISTS(SELECT * FROM TestTable) THEN
1
ELSE
0
END
END
RETURN #Result
END
While trying it in SQL Server executing the following statement:
SELECT dbo.CheckIfRecordsExistInTestTable()
Whenever TestTable exists it returns my expected result. But whenever it does not, SQL Server raises an exception (Invalid object name 'TestTable') and I cannot get what I expect (I want a zero return value in this situation).
So what do you propose to do for this problem which can be coded to a scalar function?
The other answer gives a correct workaround.
As to why you are getting the problem...
This is a compile time error.
If the statement references a non existent object compilation is deferred until just before execution, but still eventually the whole statement needs to be compiled into an execution plan before it is executed.
This fails when the table doesn't exist and execution of that statement doesn't even begin.
(Execution plan that it tries to create - using a passthru predicate to avoid evaluation of the condition if the CASE not met)
In the workaround the SELECT against testtable is moved into a different statement. Compilation of this statement is still deferred and as the statement is never executed all works fine.
Try changing the function like this
CREATE FUNCTION Checkifrecordsexistintesttable()
returns INT
BEGIN
DECLARE #Result INT
IF Object_id('TestTable') IS NULL
SET #Result = 0
ELSE
SELECT #Result = CASE
WHEN EXISTS(SELECT 1 FROM testtable) THEN 1
ELSE 0
END
RETURN #Result
END;
To know more about the reason behind the error you are getting check Martin's answer.
update function like this:
CREATE FUNCTION CheckIfRecordsExistInTestTable()
RETURNS INT
BEGIN
DECLARE #Result INT
SELECT #Result = case when count(1) = 0 then 0 else 1 end from sys.tables where name = 'TestTable'
RETURN #result
END
I am wondering why the table variables inside while loop does not behave like other variables. Table variables created only once and will be used across through out whole looping. but other variables getting initialized every time when loop increases.
Check out the below code for more info
declare #tt int
set #tt =10
while #tt>0
begin
declare #temptable table(id int identity(1,1),sid bigint)
insert into #temptable
select #tt union all
select #tt + 1
select * from #temptable
--delete from #temptable
set #tt=#tt-1
end
is this a bug??
Your premise is wrong. Other variables don't get reinitialised every time the declare statement is encountered either.
set nocount on
declare #tt int
set #tt =10
while #tt>0
begin
declare #i int
set #i = isnull(#i,0) + 1
print #i
set #tt=#tt-1
end
Prints
1
2
...
9
10
As expected
SQL Server variable scope is per batch or the entire function/procedure/trigger, not per black/nested construct
http://msdn.microsoft.com/en-us/library/ms187953.aspx:
The scope of a variable is the range
of Transact-SQL statements that can
reference the variable. The scope of a
variable lasts from the point it is
declared until the end of the batch or
stored procedure in which it is
declared.
Though it is old post just wann add my comments
set nocount on
declare #tt int
set #tt =10
while #tt>0
begin
declare #i int=0
set #i = #i + 1
print #i
set #tt=#tt-1
end
Results:
1
1
1
1
1
1
1
1
1
1
If you want to load the table variable each time the loop executes. DROP FROM #Tablevariable once work done within the loop.