0

Hoping that I can get some assistance with something, I currently have a table with 3 columns, ID int, Name varchar(20), ScriptText varchar(500). ID is just a auto incremental ID, Name is a Name give to the ScriptText, ScriptText is a piece of SQL code, it will return a number or a single piece of text. What I want to do is run through each record, executing the ScriptText, once the script text is executed and returns a value to be stored in a variable, I will later need to compare this against another table. I have tried various ways but I can execute all the code in the ScriptText column but am not able to store the ID or Name in a variable so I can use all three of them. I have come across a piece of code that looks like it should be doing what I need it to do but cannot make it work.

    DECLARE @Table table (RID BIGINT IDENTITY(1,1) PRIMARY KEY CLUSTERED, 
                        SQLText NVARCHAR(MAX) )

DECLARE  @StatementMax INT 
        ,@statementMin INT
        ,@isTest TINYINT = 0
        ,@SQLStatement NVARCHAR(MAX)
        ,@StoreOutputData varchar(1000) = '';
-- Insert SQL Into Temp Table
INSERT INTO @table (SQLText)
VALUES ('SELECT @@Version');
INSERT INTO @table (SQLText)
VALUES ('SELECT SERVERPROPERTY(''ProductVersion'')')


SELECT @statementMAX = MAX(RID), @statementMIN = MIN(RID)  FROM @table

IF @isTest = 1 BEGIN SELECT *, @statementMax AS MaxVal, @StatementMin AS MinVal FROM @Table END
-- Start the Loop
WHILE @StatementMax >= @statementMin
BEGIN
    SELECT @SQLStatement = SQLText FROM @table WHERE RID = @statementMin 

    IF @isTest = 1 BEGIN SELECT 'I am executing: ' + @SQLStatement AS theSqlBeingRun, GETDATE(), @statementMin, @StatementMax END  
    ELSE 
    BEGIN 
       EXECUTE sp_ExecuteSQL N'SELECT @OutVariable = CONVERT(NVARCHAR(1000), SERVERPROPERTY(''ProductVersion''))', N'@OutVariable varchar(1000) OUTPUT', @OutVariable = @StoreOutputData OUTPUT;
       SELECT @StoreOutputData;
    END
        DELETE FROM @table WHERE RID = @statementMin    
        SELECT @statementMIN = MIN(RID)  FROM @Table       
    IF @isTest = 1 BEGIN  SELECT * FROM @table END

END

Above amendments as per DK5

At the end when it executes the statements e.g. select @@Version I would expect it to show in the output as

"Microsoft SQL Server 2014 - 12.0.4100.1 (X64) Apr 20 2015 17:29:27 Copyright (c) Microsoft Corporation Enterprise Edition (64-bit) on Windows NT 6.1 (Build 7601: Service Pack 1)"

as per my SQL installation but instead it just shows

"I am executing: SELECT @@Version"

If anyone could assist with making this example work or have a better suggestion for my problem it would be much appreciated.

My final result as per discussion should look like

RID      SQLText
1        Microsoft SQL Server 2014 - 12.0.4100.1 (X64) 
2        12.0.4100.1

I have used the above entire statement as an example as to put down everything would not be possible, at the end of the day I have a table that currently has 19 sql statements in it as well as various columns that have data related to the sql statement, hence the reason I want to bring back further information after just running the select statement.

PJD
  • 743
  • 2
  • 12
  • 38
  • 2
    Possible duplicate of [How to get sp\_executesql result into a variable?](http://stackoverflow.com/questions/803211/how-to-get-sp-executesql-result-into-a-variable) – Pred Feb 27 '17 at 17:03
  • 2
    But your `@IsTest` value is 1, so you're not executing the statement, you're only executing `SELECT 'I am executing: ' + @SQLStatement` – James Z Feb 27 '17 at 17:13
  • Hi James, thanks for that, the obvious as you pointed out not being so obvious, think I have been looking at this for too long....though I suppose the question is why default it to 1 in the Declare statement in the first place, I suppose its one of the pitfalls at looking at someone else's code and not fully understanding it. – PJD Feb 27 '17 at 17:36
  • Sometimes using a debugger can be quite useful! – Giorgos Altanis Feb 27 '17 at 17:37

1 Answers1

0

It appears that the issue is with your Bit flag variable @isTest.

If you look at this code snippet:

IF @isTest = 1 BEGIN 
    SELECT 'I am executing: ' + @SQLStatement AS theSqlBeingRun, GETDATE(), @statementMin, @StatementMax 
END ELSE BEGIN 
    EXECUTE sp_ExecuteSQL @SQLStatement                 
END

When the variable @isTest is set to 1 then the script stored in the variable @SQLStatement is not executed. The script is appended as it is to the text in the SELECT clause. If the variable @isTest was set to something other than 1, then the ELSE branch of the If Else check would have been executed, which actually executes the statement.

The behaviour you want to see can be achieved by shifting the @isTest variable to anything other than 1 for example DECLARE @isTest int = 0.

There are more advanced things that can be done, such as using CROSS APPLY, but the issue you are facing is probably just related to this flag variable.

EDIT 1: To fetch data from sp_ExecuteSQL you can use this:

DECLARE @StoreOutputData varchar(1000) = '';
EXECUTE sp_ExecuteSQL N'SELECT @OutVariable = CONVERT(NVARCHAR(1000), SERVERPROPERTY(''ProductVersion''))', N'@OutVariable varchar(1000) OUTPUT', @OutVariable = @StoreOutputData OUTPUT;
SELECT @StoreOutputData;
DK5
  • 317
  • 3
  • 15
  • thanks for the response DK, I did some playing around last night based on one of the other suggestions and managed to work it out, something I am struggling with is, is there a way to assign the result of the sp_ExecuteSQL SQLStatement to a variable and also include the statementMin and statementMax once the statement has been successfully executed? – PJD Feb 28 '17 at 08:28
  • Yup, let me guide you on that. Its just a basic syntax which you can check from MSDN. https://msdn.microsoft.com/en-us/library/ms188001.aspx. I am also updating the code to show fetching an output from the `sp_ExecuteSQL` statement. – DK5 Feb 28 '17 at 09:12
  • Hi Dan, I have added in the amendments as shown, first it asked me to declare FetchCustomerTypeKeys, I declared this as nvarchar and then receive the message "Implicit conversion from data type sql_variant to varchar is not allowed. Use the CONVERT function to run this query." I am hoping that this all works with my scenario as I have tried doing this before but for some reason I was returning turning counts for all my select as part of the sp_executesql command but then I was also returning the same results when putting the SELECT StoreOutputData statement below which meant I was doubling – PJD Feb 28 '17 at 09:43
  • Whoops, it should not be `@FetchCustomerTypeKeys`, it should be `@StoreOutputData` instead. Updating the commands to convert the data type and remove the error as well, please try that once. – DK5 Feb 28 '17 at 09:52
  • 1
    Thanks for all the help with this, not something I have tried before and trying to understand it as we go through, I have made the changes that you posted and I am now not getting any errors but the same result posted twice, I get the ProductVersion twice and no Version? I cannot currently see how I can show the statementMin and statementMax with this current setup, would it be easier if I re-posted what my entire script now looks like with your added assistance? – PJD Feb 28 '17 at 10:02
  • Yes that could be helpful. You can also use this code snippet and fetch multiple output variables from this and then insert those variables in the table. Can you tell me what is the final result that you are desiring looks like as well? – DK5 Feb 28 '17 at 10:04
  • I have amended my original query as discussed! – PJD Feb 28 '17 at 10:14
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/136853/discussion-between-dk5-and-pjd). – DK5 Feb 28 '17 at 12:06
  • See to obtain what you desire we do need to return the output of the queries by using `sp_ExecuteSQL` as i showed. But for that you must update your SQL queries. They should have a variable added like we use the `@OutVariable`. So either all of the statements that you have in your table, which are to be executed, require to have that `@OutVariable` or you need to use `REPLACE` to update the `SELECT` statement with SELECT '@OutVariable`. But then again this is successful only if you are only extracting one output at a time, otherwise the replace needs to be slightly more complex. – DK5 Mar 02 '17 at 08:01