I have some TSQL used in classic asp like this:
Declare #tbl TABLE(some columns)
Declare #somevarables
Declare myCur CURSOR
For
Select something From my_table
Open myCur
Fetch Next From myCur Inti somevarables
While (##Fetch_Status<>-1)
Begin
some processimg
......
Insert Into #tbl(...)
Values(...)
Fetch Next From myCur Inti somevarables
End
Deallocate myCur
Select * From #tbl
The scripts worked well in SQL Query Analyzer. However, when I run it in an ASP page, there's no rowset returned, nor error message.
Who can tell me why?
Thanks!
The problem is that you're inserting multiple times and each time your rows affected count will generate a closed recordset.
Simple fix is to make sure in your T-SQL you first SET NOCOUNT ON;, this will stop the row counts and the only recordset returned will be your end SELECT.
Related
For a homework assignment, I'm trying to build a trigger that allows for multiple inserts/updates/deletes by utilizing a cursor. We have to use a cursor in order to practice the syntax. We know that there are very few practical scenarios for cursors in a production environment.
Here's what I'm trying to accomplish:
For each row inserted into the TAL_ORDER_LINE table, update the ON_HAND value in the TAL_ITEM table by subtracting the NUM_ORDERED value from the stored ON_HAND value.
Table Structure:
Current Query:
ALTER TRIGGER update_on_hand
ON TAL_ORDER_LINE
AFTER INSERT AS
DECLARE #vItemNum as char
DECLARE #vNumOrdered as int
DECLARE new_order CURSOR FOR
SELECT ITEM_NUM, NUM_ORDERED
FROM inserted
OPEN new_order;
FETCH NEXT FROM new_order INTO #vItemNum, #vNumOrdered;
WHILE ##FETCH_STATUS=0
BEGIN
UPDATE TAL_ITEM
SET ON_HAND = ON_HAND - #vNumOrdered
WHERE ITEM_NUM = #vItemNum
FETCH NEXT FROM new_order INTO #vItemNum, #vNumOrdered;
END
CLOSE new_order
DEALLOCATE new_order
My Insert Query:
INSERT INTO TAL_ORDER_LINE (ORDER_NUM, ITEM_NUM, NUM_ORDERED, QUOTED_PRICE)
VALUES (51626, 'KL78', 10, 10.95), (51626, 'DR67', 10, 29.95)
It runs successfully, but does not affect the ON_HAND value. I think the biggest problem is that I'm struggling to understand cursor syntax, especially the INTO clause in the FETCH statement and how data from the 'inserted' table is passed into the cursor. What do I need to know to get this to work? Thanks in advance!
Your problem is likely due to this:
DECLARE #vItemNum as char
it is HIGHLY unlikely that the ItemNum column is a single character. For future reference, you should always verify that you variable definitions are consistent with the values you expect to store in them. And as has been hinted - you will get better answers by posting a complete script rather than a picture.
Big question,how you gonna debug ?
Is On_Hand col NULL , then do this isnull(on_Hand,0)
DECLARE #vItemNum as char
DECLARE #vNumOrdered as int
DECLARE new_order CURSOR FOR
SELECT ITEM_NUM, NUM_ORDERED
FROM TAL_ORDER_LINE
OPEN new_order;
FETCH NEXT FROM new_order INTO #vItemNum, #vNumOrdered;
WHILE ##FETCH_STATUS=0
BEGIN
--UPDATE TAL_ITEM
--SET ON_HAND = ON_HAND - #vNumOrdered
--WHERE ITEM_NUM = #vItemNum
print #vItemNum
print vNumOrdered
FETCH NEXT FROM new_order INTO #vItemNum, #vNumOrdered;
END
CLOSE new_order
DEALLOCATE new_order
Try this :
ALTER TRIGGER update_on_hand ON TAL_ORDER_LINE
FOR INSERT AS
BEGIN
UPDATE TI
SET TI.ON_HAND = TI.ON_HAND - I.NUM_ORDERED
TAL_ITEM TI INNER JOIN
INSERTED I ON I.ITEM_NUM = TI.ITEM_NUM
END
Changed Trigger to FOR INSERT Trigger
Removed Cursor
Note: NOT Tested. ( If you post the sql scripts for create table + sample inserts I can give it a try )
I have to fetch all columns names for all tables in a specific schema.
I did it without any problem in PL/SQL for an oracle Database but in DB2 I can't seem to make it work.
Here is my code :
BEGIN
declare cur1 cursor for
select TABNAME
from syscat.tables
where tabschema = 'SchemaX';
open cur1;
fetch cur1 into i;
while SQLCODE <> 100
do
select * from SYSCAT.COLUMNS where tabname = i;
end while;
close cur1;
END
it doesn't seems to like my select in the while loop.
Anybody have done this before?
Thank you!
First you need to create one proc and then call it to get the result set.
Without creating procedure if you run it it will run but will give 0 zero results.
CREATE OR REPLACE PROCEDURE MY_PROC_FOR_TESTING
DYNAMIC RESULT SETS 1
BEGIN
FOR I AS C1 cursor WITH HOLD for select TABNAME from syscat.tables where tabschema = 'SchemaX'
DO
BEGIN
DECLARE C_DISBURS_RPT CURSOR WITH RETURN TO CLIENT FOR
select * FROM SYSCAT.COLUMNS where tabname =I.TABNAME;
OPEN C_DISBURS_RPT;
END;
END FOR;
END!
CALL MY_PROC_FOR_TESTING!
Note: End of the statement should be mentioned at the statement termination box if it is IBM client.
I have a table with 700 rows. What I want to do is, to execute `select * from table_name' query on it and whatever result I will get want to store it in a variable and after that is done, want to traverse through each record for processing purpose? How do I achieve it? Any help??
Thanks in adv,
-saurabh
you want something which is called cursors
Cursors
You use a cursor to fetch rows returned by a query. You retrieve the rows into the cursor using a query and then fetch the rows one at a time from the cursor.
Steps
Declare variables to store the column values for a row.
Declare the cursor, which contains a query.
Open the cursor.
Fetch the rows from the cursor one at a time and store the column values in the variables declared in Step 1. You would then do something with those variables; such as display them on the screen, use them in a calculation, and so on.
Close the cursor.
hopefully this might help you cursor
here is an example I use to start with
USE pubs
GO
-- Declare the variables to store the values returned by FETCH.
DECLARE #au_lname varchar(40), #au_fname varchar(20)
DECLARE authors_cursor CURSOR FOR
SELECT au_lname, au_fname FROM authors
--WHERE au_lname LIKE 'B%'
ORDER BY au_lname, au_fname
OPEN authors_cursor
-- Perform the first fetch and store the values in variables.
-- Note: The variables are in the same order as the columns
-- in the SELECT statement.
FETCH NEXT FROM authors_cursor
INTO #au_lname, #au_fname
-- Check ##FETCH_STATUS to see if there are any more rows to fetch.
WHILE ##FETCH_STATUS = 0
BEGIN
-- Concatenate and display the current values in the variables.
PRINT #au_fname
-- This is executed as long as the previous fetch succeeds.
FETCH NEXT FROM authors_cursor
INTO #au_lname, #au_fname
END
CLOSE authors_cursor
DEALLOCATE authors_cursor
GO
I need some tip on tuning some TSQL to execute faster, it's taking way too long although it works. This may be because I'm fetching a key from another table before I can do the insert, any ideas anyone?
DECLARE db_cursorReads CURSOR FOR SELECT
[MeterId]
,[MeterRead]
FROM MdsReadsImports;
declare #PremiseMeterId int;
declare #MeterId nvarchar(24);
declare #MeterRead int;
OPEN db_cursorReads;
FETCH NEXT FROM db_cursorReads INTO
#MeterId
,#MeterRead;
WHILE ##FETCH_STATUS = 0
BEGIN
set #PremiseMeterId = (select top 1 PremiseMeterId from PremiseMeters where MeterId = #MeterId)
insert into PremiseMeterReads (MeterRead,PremiseMeterId)
values (#MeterRead, #MPremiseMeterId)
FETCH NEXT FROM db_cursorReads INTO
#MeterId
,#MeterRead;
END;
CLOSE db_cursorReads;
DEALLOCATE db_cursorReads;
I see you are retrieving PremiseMeterId but not using it in the script you posted. Perhaps you can ditch the cursor and perform a single set-based query:
INSERT INTO PremiseMeterReads (MeterRead,MeterId)
SELECT
[MeterRead]
,[MeterId]
FROM MdsReadsImports;
First, I note that you are setting but not using #PremiseMeterID.
Second, you seem to be doing this:
insert into PremiseMeterReads (MeterRead, MeterId)
select MeterRead, MeterId
from MdsReadsImports;
A set based operation should be much faster than using a cursor.
I have a stored procedure, which contains a simple select statement:
ALTER PROCEDURE [dbo].[TransferAuditRecords]
As
SET NOCOUNT ON
SET XACT_ABORT ON
Declare #UserCode As varchar(50)
DECLARE AuditCursor CURSOR FOR
select top 1 UserCode from [AuditDatabaseServer].AuditDatabase.dbo.dbaudit where auditdate >= '2012-09-04'
Open AuditCursor
FETCH NEXT FROM AuditCursor INTO #UserCode
WHILE ##FETCH_STATUS = 0
BEGIN
Print #Usercode
FETCH NEXT FROM AuditCursor INTO #UserCode
END
Close AuditCursor
Deallocate AuditCursor
There are a few lines of code missing, which I excluded as they are irrelevant to the question.
If I execute the SQL statement without the stored procedure i.e. in SQL Studio Manager 2005 then I get a different output than if I run the stored procedure i.e. the top reference returned is different. Why are the outputs different?
I am fairly sure that the reason for this is because SQL Server uses a different execution plan for compiled code is comparison to code being run in SQL Studio Manager. I wanted to check though.
Use an ORDER BY clause to predictably indicate which row is selected.
e.g. select top 1... order by auditdate
Unrelated:: is the use of a cursor required by part of the code you removed? I guess so, otherwise a simpler "select top 1 #UserCode = UserCode from..." would be enough.