I have the following stored procedure that calculates the maximum values for multiple columns. I have achieved the same result using a lengthy union select, however, I am just interested in the performance difference. Using a C# direction SQL parameter of either output or a return value, I would like to only return the value of the select statement marked "-- NEED TO GET THIS VALUE RETURNED".
I tried creating an OUTPUT variable, then using the SET syntax to store the value, then the RETURN syntax. But to no avail. Kept of getting errors that I need to create variables that are already there. I am not understanding the scope of the variables it seems. (I have removed that from the code in the meantime)
Here is my SP:
CREATE PROCEDURE sp_GetMaximumMax
@FromDate DateTime,
@ToDate DateTime,
@TableName VarChar(150)
AS
DECLARE @SQL NVARCHAR(512), @ColumnName VARCHAR(150)
DECLARE @Result TABLE (Result int)
DECLARE read_cursor CURSOR FOR
SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = @TableName
AND (column_name != 'id' AND column_name !='time' AND column_name !='no')
OPEN read_cursor;
FETCH NEXT FROM read_cursor INTO @ColumnName;
SET @SQL = 'SELECT MAX(['+@ColumnName+']) FROM '+@TableName+' WHERE [time] BETWEEN '''+CONVERT(VARCHAR, @FromDate, 120)+''' AND '''+CONVERT(VARCHAR, @ToDate, 120)+'''';
WHILE @@FETCH_STATUS = 0
BEGIN
Print @SQL
INSERT @Result
EXEC(@SQL);
FETCH NEXT FROM read_cursor
END
-- NEED TO GET THIS VALUE RETURNED
SELECT MAX(Result) AS MaxVar from @Result
CLOSE read_cursor;
DEALLOCATE read_cursor;
Herewith my revised code:
CREATE PROCEDURE sp_GetMaximumAvg
@FromDate DateTime,
@ToDate DateTime,
@TableName VarChar(150)
AS
CREATE TABLE #Fields(FieldName VARCHAR(150)) -- store column names
CREATE TABLE #Data(FieldName DECIMAL) -- store max values
DECLARE @ColumnName VARCHAR(150)
DECLARE @SQL VARCHAR(512)
-- add fields into field table
INSERT INTO #Fields (FieldName) SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @TableName AND (column_name != 'id' AND column_name !='time' AND column_name !='no')
DECLARE @Field VARCHAR(150)
DECLARE @MyOutput INT
DECLARE ReadDaRow CURSOR
FOR SELECT * FROM #Fields
OPEN ReadDaRow
FETCH ReadDaRow INTO @Field
WHILE(@@FETCH_STATUS=0) BEGIN
SET @SQL = 'SELECT AVG(['+@Field+']) FROM '+@TableName+' WHERE [time] BETWEEN '''+CONVERT(VARCHAR, @FromDate, 120)+''' AND '''+CONVERT(VARCHAR, @ToDate, 120)+'''';
PRINT @SQL
INSERT INTO #Data EXEC(@SQL)
FETCH ReadDaRow INTO @Field
END
SELECT @MyOutput = MAX(FieldName) FROM #Data
RETURN @MyOutput
CLOSE ReadDaRow
DEALLOCATE ReadDaRow
DROP TABLE #Fields
DROP TABLE #Data
c# example of executing the SP:
SqlCommand GetMaxCmd = new SqlCommand("sp_GetMaximumAvg", SQLConnection);
GetMaxCmd.CommandType = System.Data.CommandType.StoredProcedure;
GetMaxCmd.Parameters.Add("@FromDate", SqlDbType.DateTime).Value = DateTime.Parse(from_date);
GetMaxCmd.Parameters.Add("@ToDate", SqlDbType.DateTime).Value = DateTime.Parse(to_date);
GetMaxCmd.Parameters.Add("@TableName", SqlDbType.VarChar).Value = table_name;
SqlParameter Output = GetMaxCmd.Parameters.Add("@MyOutput", SqlDbType.SmallInt);
Output.Direction = ParameterDirection.ReturnValue;
try
{
GetMaxCmd.ExecuteNonQuery();
Max = Convert.ToInt32(Output.Value);
}
catch (NullReferenceException) { }
catch (FormatException) { }
catch (SqlException) { }