I have the following table
Create table TestScene(
string varchar(60))
insert into TestScene values ('t_Scene');
insert into TestScene values ('v_Scene');
On this table,I want to parse each string and I'm doing that,the problem is that it's doubling the last field and I don't know why.Do you see what I'm missing?
DECLARE #contor int
DECLARE #stringut varchar(50)
DECLARE cursorName CURSOR -- Declare cursor
FOR
Select string FROM TestScene
Select #contor=count(*) from TestScene
OPEN cursorName -- open the cursor
print #contor
FETCH NEXT FROM cursorName INTO #stringut
PRINT #stringut+' ' -- print the name
WHILE #contor>0
BEGIN
FETCH NEXT FROM cursorName INTO #stringut
declare #i int,#j int
set #j=charindex(#stringut,'_')
set #i=0
While #j<>0
begin
declare #str varchar
set #str = SUBSTRING(#stringut,#i,#j-1-#i)
print #str+' '
set #i=#j
set #j=charindex(#stringut,'_')
end
PRINT #stringut -- print the name
set #contor=#contor-1
END
CLOSE cursorName -- close the cursor
DEALLOCATE cursorName -- Deallocate the cursor
That's becuase you have fetched value in cursor twice one before while loop and one within it. Write as:
DECLARE #contor int
DECLARE #stringut varchar(50)
DECLARE cursorName CURSOR -- Declare cursor
FOR
Select string FROM TestScene
Select #contor=count(*) from TestScene
OPEN cursorName -- open the cursor
print #contor
--FETCH NEXT FROM cursorName INTO #stringut-- no need
PRINT #stringut+' ' -- print the name
WHILE #contor>0
BEGIN
FETCH NEXT FROM cursorName INTO #stringut
declare #i int,#j int
set #j=charindex(#stringut,'_')
set #i=0
While #j<>0
begin
declare #str varchar
set #str = SUBSTRING(#stringut,#i,#j-1-#i)
print #str+' '
set #i=#j
set #j=charindex(#stringut,'_')
end
PRINT #stringut -- print the name
set #contor=#contor-1
END
CLOSE cursorName -- close the cursor
DEALLOCATE cursorName -- Deallocate the cursor
Related
How do I select multiple columns in a cursor?
I tested the below code but it's returning/printing nothing.
DECLARE #DateAdded VARCHAR(50)
DECLARE #IdEmployee NVARCHAR(20)
DECLARE #EmailAddress VARCHAR(100)
DECLARE #Subject VARCHAR(50)
DECLARE #Message VARCHAR(100)
DECLARE #DateSent VARCHAR(50)
-- 2 - Declare Cursor
DECLARE db_cursor CURSOR FOR
-- Populate the cursor with your logic
-- * UPDATE WITH YOUR SPECIFIC CODE HERE *
SELECT
#DateAdded, #IdEmployee, #EmailAddress,
#Subject, #Message, #DateSent
FROM #tblLeaveNotifToApprover
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO #DateAdded, #IdEmployee, #EmailAddress, #Subject, #Message, #DateSent
WHILE ##FETCH_STATUS = 0
BEGIN
-- 4 - Begin the custom business logic
-- * UPDATE WITH YOUR SPECIFIC CODE HERE *
PRINT CONVERT(VARCHAR,#DateAdded)
FETCH NEXT FROM db_cursor INTO #DateAdded, # IdEmployee, #EmailAddress, #Subject, #Message, #DateSent
END
CLOSE db_cursor
DEALLOCATE db_cursor
Initially wanted to print all that columns in each row, but after running the snippet/code it nothing displays, I also tried converting the variables to varchar same result is thrown.
I expect that all the columns of my 7 rows will be print out.
This is wrong
DECLARE db_cursor CURSOR FOR
-- Populate the cursor with your logic
-- * UPDATE WITH YOUR SPECIFIC CODE HERE *
SELECT
#DateAdded, #IdEmployee, #EmailAddress,
#Subject, #Message, #DateSent
FROM #tblLeaveNotifToApprover
You need to replace the variables in this SELECT statement with the actual column names from the table. You don't refer to your local variables until the FETCH statement.
Think of your CURSOR as a selected set of data from the source tables that you will then iterate through.
Your snippet contains the hints to identify what is in the CURSOR, in your case refer to
-- Populate the cursor with your logic
-- * UPDATE WITH YOUR SPECIFIC CODE HERE *
In your case, your are trying to populate your CURSOR using the values from the variables you have declared using the statement:
SELECT #DateAdded,
#IdEmployee,
#EmailAddress,
#Subject,
#Message,
#DateSent
FROM #tblLeaveNotifToApprover
Now, since you have not populated those variables yet they are all NULL
What you then do is SELECT the variables that you have just declared back into the variables !!!!!
FETCH NEXT FROM db_cursor INTO #DateAdded,#IdEmployee,#EmailAddress,#Subject,#Message,#DateSent
WHILE ##FETCH_STATUS = 0
So it is little surprise that when you try to print these you get nothing returned.
Go back to your DECLARE CURSOR and ensure that you are actually selecting a data set to iterate through. a CURSOR should generally always be kind of like a temporary table. If we assume that your temp table #tblLeaveNotifToApprover has column names that match your variable names then you need:
DECLARE db_cursor CURSOR FOR
SELECT DateAdded,
IdEmployee,
EmailAddress,
Subject,
Message,
DateSent
FROM #tblLeaveNotifToApprover
I want to monitor few SQL SERVER instances (about 31), and I want to prepare a procedure that will aggregate data from instances based on sys.servers list, but I cant dynamically ask a server.
DECLARE #instance_name sysname;
DECLARE instance_cursor CURSOR FOR
select data_source from sys.servers where is_linked = 1;
OPEN instance_cursor
FETCH NEXT FROM instance_cursor INTO #instance_name
WHILE ##FETCH_STATUS = 0
BEGIN
--Do something on a linked server
SELECT 1 FROM #instance_name.master.sys.master_files
FETCH NEXT FROM instance_cursor INTO #instance_name
END
CLOSE instance_cursor
DEALLOCATE instance_cursor
USE master
GO
IF OBJECT_ID('tempdb..#server_info') IS NOT NULL
DROP TABLE #server_info
CREATE TABLE #server_info
(
Col1 SQL_VARIANT,
Col2 SQL_VARIANT,
Col3 SQL_VARIANT,
Col4 SQL_VARIANT
) -- change data type as needed.
DECLARE #instance_name NVARCHAR(255);
DECLARE #sql NVARCHAR(MAX)
DECLARE instance_cursor CURSOR FOR
SELECT name FROM master.sys.servers WHERE is_linked = 1
ORDER BY name
OPEN instance_cursor
FETCH NEXT FROM instance_cursor INTO #instance_name
WHILE ##FETCH_STATUS = 0
BEGIN
--Do something on a linked server
SET #sql = 'INSERT INTO #server_info (Col1,Col2,Col3,Col4) SELECT .... FROM ' + #instance_name + '.master.sys...'
PRINT #sql -- verify for your syntax
EXEC (#sql)
FETCH NEXT FROM instance_cursor INTO #instance_name
END
CLOSE instance_cursor
DEALLOCATE instance_cursor
SELECT * FROM #server_info
I'm not found a perfect solution for this, but:
CREATE PROCEDURE [kk].[query_ls]
#SQL NVARCHAR(MAX)
AS
BEGIN
DECLARE #query NVARCHAR(MAX);
DECLARE #instance_name sysname;
DECLARE instance_cursor CURSOR FOR
select data_source from sys.servers where is_linked = 1;
OPEN instance_cursor
FETCH NEXT FROM instance_cursor INTO #instance_name
WHILE ##FETCH_STATUS = 0
BEGIN
SET #query = REPLACE(#SQL,'#server#',#instance_name )
EXEC (#query)
FETCH NEXT FROM instance_cursor INTO #instance_name
END
CLOSE instance_cursor
DEALLOCATE instance_cursor
END
And usage example:
EXEC [kk].[query_ls] N'use _dba INSERT INTO kk.cpuUsagePerDB select *,getdate() from [#server#]._dba.kk.[V_cpuUsagePerDB]'
Another solution can be achieved by OPENQUERY
I have a table(Lets say'A') that contains the list of all tables in a database.I have defined a cursor that iterate through the tables name in 'A'.I want to update the table column defined in a cursor.
I have created 2 cursors.One to iterate over the tables names and other one to iterate over the column names.
DECLARE #MyCursor CURSOR;
DECLARE #MyField nvarchar(255);
BEGIN
SET #MyCursor = CURSOR FOR
select distinct Table_name from DataTable where Data <>'No'
set #a=0
OPEN #MyCursor
FETCH NEXT FROM #MyCursor
INTO #MyField
WHILE ##FETCH_STATUS = 0
BEGIN
DECLARE #column_cursor CURSOR;
DECLARE #columnField nvarchar(255);
SET #column_cursor = CURSOR FOR
select Column_name from DataTable where TABLE_NAME=#MyField and Data
<>'No'
OPEN #column_cursor
FETCH NEXT FROM #column_cursor
INTO #columnField
WHILE ##FETCH_STATUS = 0
BEGIN
update #MyField set #columnField=''+#MyField+'_'+#columnField+#a
FETCH NEXT FROM #column_cursor
INTO #columnField
END;
CLOSE #column_cursor ;
DEALLOCATE #column_cursor;
FETCH NEXT FROM #MyCursor
INTO #MyField
END;
CLOSE #MyCursor ;
DEALLOCATE #MyCursor;
END;
Here in the update statement #MyField is giving error :"Must declare the table variable #MyField".
You are on good way but you can't use variable on table name place , you need to build your update command in variable and then execute dynamic sql.
You can see: Creating a dynamic sql query
in your case someting like
declare #sqlCommand varchar(max)
declare #MyField varchar(255) = 'table_name'
declare #columnField varchar(255) = 'column_NAME'
declare #columnValue varchar(255) = 'column_value'
set #sqlCommand = 'update '+ #MyField +' set '+#columnField+' = ' +#columnValue+ ' where 1=1;'
--select #sqlCommand
EXEC (#sqlCommand)
I have two cursors, I want to loop through first one, and use its values as parameters for the second cursor and then do some processing. I know how to do this in PL-SQL, but T-SQL puzzles me.
I have gotten so far. For some reason the nested cursor does not print anything.
DECLARE #period DATE
DECLARE #table_type VARCHAR(2)
DECLARE #clmn_clr VARCHAR(100)
DECLARE #clmn_per VARCHAR(100)
DECLARE #period_num INT
DECLARE #period_date DATE
DECLARE #table_type2 VARCHAR(2)
DECLARE c_table CURSOR FOR SELECT period,
table_type
FROM #period_table
DECLARE c_period CURSOR LOCAL FAST_FORWARD FOR SELECT clmn_clr,
clmn_per,
period_num,
period_date,
table_type
FROM #column_period
WHERE table_type = #table_type
OPEN c_table
FETCH NEXT FROM c_table
INTO #period, #table_type
WHILE ##FETCH_STATUS = 0
BEGIN
print #period
print #table_type
print '------------'
FETCH NEXT FROM c_table
INTO #period, #table_type
--Nested cursor
OPEN c_period
FETCH NEXT FROM c_period
INTO #clmn_clr, #clmn_per, #period_num, #period_date, #table_type2
BEGIN
print #clmn_clr
print #clmn_per
print #period_num
print #period_date
print #table_type2
FETCH NEXT FROM c_period
INTO #clmn_clr, #clmn_per, #period_num, #period_date, #table_type2
END
CLOSE c_period
DEALLOCATE c_period
END
CLOSE c_table
DEALLOCATE c_table
It does print the first line from cursor c_table but that is all.
Also, any comments for how to do this in T-SQL better are very welcomed.
There is no need in nesting, here is the only cursor that can do everything:
DECLARE c_period CURSOR LOCAL FAST_FORWARD FOR
SELECT p.period,
c.clmn_clr,
c.clmn_per,
c.period_num,
c.period_date,
c.table_type
FROM #period_table p
INNER JOIN #column_period c
ON c.table_type = p.table_type
ORDER BY p.table_type
I never tested it but id does not seem to me that MSSQL allows something like "dynamic parameter binding" for cursor. Since you opened it - it's done. It only can react on data modifications if appripriate options applied.
You may reopen cursor if you still need nesting for any purpose. Fetch #table_type from outer cursor, then DECLARE ... OPEN nested cursor.
Also note that strings to print (if this is your real subject) can be obtained with single select, withot any cursors (search "string aggregation" for mssql).
Here is working solution I have found - I only moved the nested cursor inside.
DECLARE #period DATE
DECLARE #table_type VARCHAR(2)
DECLARE #clmn_clr VARCHAR(100)
DECLARE #clmn_per VARCHAR(100)
DECLARE #period_num INT
DECLARE #period_date DATE
DECLARE #table_type2 VARCHAR(2)
DECLARE c_table CURSOR FOR SELECT period,
table_type
FROM #period_table
--Fetch first row
OPEN c_table
FETCH NEXT FROM c_table
INTO #period, #table_type
--Loop starts here, until it is empty
WHILE ##FETCH_STATUS = 0
BEGIN
print #period
print #table_type
print '----------'
--Nested cursor
DECLARE c_period CURSOR LOCAL FAST_FORWARD FOR SELECT clmn_clr,
clmn_per,
period_num,
period_date,
table_type
FROM #column_period
WHERE table_type = #table_type
OPEN c_period
FETCH NEXT FROM c_period
INTO #clmn_clr, #clmn_per, #period_num, #period_date, #table_type2
WHILE ##FETCH_STATUS = 0
BEGIN
print #clmn_clr
print #clmn_per
print #period_num
print #period_date
print #table_type2
FETCH NEXT FROM c_period
INTO #clmn_clr, #clmn_per, #period_num, #period_date, #table_type2
END
CLOSE c_period
DEALLOCATE c_period
FETCH NEXT FROM c_table
INTO #period, #table_type
END
CLOSE c_table
DEALLOCATE c_table
This is my Coding...
If i execute the Stored procedure which means with in the stored procedure
(Normally selecting everything and if i press execute button at top of the menu)
it is working
but
out side
how can i run the stored procedure.
i tried like this
exec uspGetAddress 'CDB0001','Bevcon Wayors Pvt Ltd','c'
but not working.
SET NOCOUNT ON
DECLARE #Cuscode varchar(250)
DECLARE #customertName VARCHAR(250)
DECLARE #custype varchar(250)
DECLARE #Cur_Product CURSOR
set #Cur_Product= cursor for select CardCode,CardName,CardType from ocrd
open #Cur_Product
fetch next
from #Cur_Product into #Cuscode,#customertName,#custype
while ##FETCH_STATUS = 0
begin
insert into custupdate (ccode,cname,ctype) values (#Cuscode,#customertName,#custype)
fetch next
from #Cur_Product into #Cuscode,#customertName,#custype
end
close #Cur_Product
deallocate #Cur_Product
You have to create the Stored Procedure before calling it :
Create Procedure uspGetAddress
#Cuscode varchar(250),
#customertName VARCHAR(250) ,
#custype varchar(250)
As
Begin
DECLARE #Cur_Product CURSOR
set #Cur_Product= cursor for select CardCode,CardName,CardType from ocrd
open #Cur_Product
fetch next
from #Cur_Product into #Cuscode,#customertName,#custype
while ##FETCH_STATUS = 0
begin
insert into custupdate (ccode,cname,ctype) values (#Cuscode,#customertName,#custype)
fetch next
from #Cur_Product into #Cuscode,#customertName,#custype
end
close #Cur_Product
deallocate #Cur_Product
End