Giving EXEC (@Variable) a Column name and Concatenation












5















I'm trying to writing a stored procedure that will check for orphan data before our customers attempt an upgrade, as orphaned records can cause issues. This is what I have thus far;



IF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'DetectOrphanDataBeforeUpgrade')
DROP PROCEDURE [dbo].[DetectOrphanDataBeforeUpgrade]
GO

CREATE PROCEDURE [dbo].[DetectOrphanDataBeforeUpgrade]

@TenantId INT = NULL

AS
BEGIN

DECLARE @OrphanAuditItems NVARCHAR(MAX)
DECLARE @OrphanAuditAnswers NVARCHAR(MAX)
DECLARE @OrphanAuditQuestion NVARCHAR(MAX)

------------------------------------------------------------------------------------------------
/* Throw an error if the TenantId is NULL or Invalid. */
------------------------------------------------------------------------------------------------
IF @TenantId IS NULL OR @TenantId NOT IN (SELECT Tenants FROM [Application].[dbo].[TenantIdNumber])

BEGIN
THROW 51000, '@TenantId is invalid because it is NULL or does not exist.', 1;
END


------------------------------------------------------------------------------------------------
/* Checks for Orphan records related to the Audits table */
------------------------------------------------------------------------------------------------
SET @OrphanAuditItems = N'SELECT COUNT(*) FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditItems]
WHERE FK_Audit NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[Audits])'

SET @OrphanAuditAnswers = N'SELECT COUNT(*) FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditAnswers]
WHERE AuditItemId NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditItems])'

SET @OrphanAuditQuestion = N'SELECT COUNT(*) FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditQuestion]
WHERE AuditId NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[Audits])'

EXEC (@OrphanAuditItems)
EXEC(@OrphanAuditAnswers)
EXEC(@OrphanAuditQuestion)

END;


At the moment, this script is working, however the output is;



Imagine 1



I want to return the results on a single line, and have each column with their own name, for example: @OrphanAuditItems result shows as column name: OrphanAuditItems, and so on.



How's the best way to achieve this?



Thanks,
Tom










share|improve this question



























    5















    I'm trying to writing a stored procedure that will check for orphan data before our customers attempt an upgrade, as orphaned records can cause issues. This is what I have thus far;



    IF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'DetectOrphanDataBeforeUpgrade')
    DROP PROCEDURE [dbo].[DetectOrphanDataBeforeUpgrade]
    GO

    CREATE PROCEDURE [dbo].[DetectOrphanDataBeforeUpgrade]

    @TenantId INT = NULL

    AS
    BEGIN

    DECLARE @OrphanAuditItems NVARCHAR(MAX)
    DECLARE @OrphanAuditAnswers NVARCHAR(MAX)
    DECLARE @OrphanAuditQuestion NVARCHAR(MAX)

    ------------------------------------------------------------------------------------------------
    /* Throw an error if the TenantId is NULL or Invalid. */
    ------------------------------------------------------------------------------------------------
    IF @TenantId IS NULL OR @TenantId NOT IN (SELECT Tenants FROM [Application].[dbo].[TenantIdNumber])

    BEGIN
    THROW 51000, '@TenantId is invalid because it is NULL or does not exist.', 1;
    END


    ------------------------------------------------------------------------------------------------
    /* Checks for Orphan records related to the Audits table */
    ------------------------------------------------------------------------------------------------
    SET @OrphanAuditItems = N'SELECT COUNT(*) FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditItems]
    WHERE FK_Audit NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[Audits])'

    SET @OrphanAuditAnswers = N'SELECT COUNT(*) FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditAnswers]
    WHERE AuditItemId NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditItems])'

    SET @OrphanAuditQuestion = N'SELECT COUNT(*) FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditQuestion]
    WHERE AuditId NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[Audits])'

    EXEC (@OrphanAuditItems)
    EXEC(@OrphanAuditAnswers)
    EXEC(@OrphanAuditQuestion)

    END;


    At the moment, this script is working, however the output is;



    Imagine 1



    I want to return the results on a single line, and have each column with their own name, for example: @OrphanAuditItems result shows as column name: OrphanAuditItems, and so on.



    How's the best way to achieve this?



    Thanks,
    Tom










    share|improve this question

























      5












      5








      5








      I'm trying to writing a stored procedure that will check for orphan data before our customers attempt an upgrade, as orphaned records can cause issues. This is what I have thus far;



      IF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'DetectOrphanDataBeforeUpgrade')
      DROP PROCEDURE [dbo].[DetectOrphanDataBeforeUpgrade]
      GO

      CREATE PROCEDURE [dbo].[DetectOrphanDataBeforeUpgrade]

      @TenantId INT = NULL

      AS
      BEGIN

      DECLARE @OrphanAuditItems NVARCHAR(MAX)
      DECLARE @OrphanAuditAnswers NVARCHAR(MAX)
      DECLARE @OrphanAuditQuestion NVARCHAR(MAX)

      ------------------------------------------------------------------------------------------------
      /* Throw an error if the TenantId is NULL or Invalid. */
      ------------------------------------------------------------------------------------------------
      IF @TenantId IS NULL OR @TenantId NOT IN (SELECT Tenants FROM [Application].[dbo].[TenantIdNumber])

      BEGIN
      THROW 51000, '@TenantId is invalid because it is NULL or does not exist.', 1;
      END


      ------------------------------------------------------------------------------------------------
      /* Checks for Orphan records related to the Audits table */
      ------------------------------------------------------------------------------------------------
      SET @OrphanAuditItems = N'SELECT COUNT(*) FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditItems]
      WHERE FK_Audit NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[Audits])'

      SET @OrphanAuditAnswers = N'SELECT COUNT(*) FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditAnswers]
      WHERE AuditItemId NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditItems])'

      SET @OrphanAuditQuestion = N'SELECT COUNT(*) FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditQuestion]
      WHERE AuditId NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[Audits])'

      EXEC (@OrphanAuditItems)
      EXEC(@OrphanAuditAnswers)
      EXEC(@OrphanAuditQuestion)

      END;


      At the moment, this script is working, however the output is;



      Imagine 1



      I want to return the results on a single line, and have each column with their own name, for example: @OrphanAuditItems result shows as column name: OrphanAuditItems, and so on.



      How's the best way to achieve this?



      Thanks,
      Tom










      share|improve this question














      I'm trying to writing a stored procedure that will check for orphan data before our customers attempt an upgrade, as orphaned records can cause issues. This is what I have thus far;



      IF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'DetectOrphanDataBeforeUpgrade')
      DROP PROCEDURE [dbo].[DetectOrphanDataBeforeUpgrade]
      GO

      CREATE PROCEDURE [dbo].[DetectOrphanDataBeforeUpgrade]

      @TenantId INT = NULL

      AS
      BEGIN

      DECLARE @OrphanAuditItems NVARCHAR(MAX)
      DECLARE @OrphanAuditAnswers NVARCHAR(MAX)
      DECLARE @OrphanAuditQuestion NVARCHAR(MAX)

      ------------------------------------------------------------------------------------------------
      /* Throw an error if the TenantId is NULL or Invalid. */
      ------------------------------------------------------------------------------------------------
      IF @TenantId IS NULL OR @TenantId NOT IN (SELECT Tenants FROM [Application].[dbo].[TenantIdNumber])

      BEGIN
      THROW 51000, '@TenantId is invalid because it is NULL or does not exist.', 1;
      END


      ------------------------------------------------------------------------------------------------
      /* Checks for Orphan records related to the Audits table */
      ------------------------------------------------------------------------------------------------
      SET @OrphanAuditItems = N'SELECT COUNT(*) FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditItems]
      WHERE FK_Audit NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[Audits])'

      SET @OrphanAuditAnswers = N'SELECT COUNT(*) FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditAnswers]
      WHERE AuditItemId NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditItems])'

      SET @OrphanAuditQuestion = N'SELECT COUNT(*) FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditQuestion]
      WHERE AuditId NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[Audits])'

      EXEC (@OrphanAuditItems)
      EXEC(@OrphanAuditAnswers)
      EXEC(@OrphanAuditQuestion)

      END;


      At the moment, this script is working, however the output is;



      Imagine 1



      I want to return the results on a single line, and have each column with their own name, for example: @OrphanAuditItems result shows as column name: OrphanAuditItems, and so on.



      How's the best way to achieve this?



      Thanks,
      Tom







      sql-server






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked 17 hours ago









      Tom_WTom_W

      423




      423






















          4 Answers
          4






          active

          oldest

          votes


















          3














          You will need to mix your 3 dynamic SQLs into 1 that returns 3 columns, or keep each dynamic SQL but mix their result at the end. There are 2 possible solutions following:





          One solution is to use UNION ALL and the PIVOT to get 1 row with 3 columns, all inside the dynamic SQL.



          Change this part:



          DECLARE @OrphanAuditItems NVARCHAR(MAX)
          DECLARE @OrphanAuditAnswers NVARCHAR(MAX)
          DECLARE @OrphanAuditQuestion NVARCHAR(MAX)

          --.....

          SET @OrphanAuditItems = N'SELECT COUNT(*) FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditItems]
          WHERE FK_Audit NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[Audits])'

          SET @OrphanAuditAnswers = N'SELECT COUNT(*) FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditAnswers]
          WHERE AuditItemId NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditItems])'

          SET @OrphanAuditQuestion = N'SELECT COUNT(*) FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditQuestion]
          WHERE AuditId NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[Audits])'

          EXEC (@OrphanAuditItems)
          EXEC(@OrphanAuditAnswers)
          EXEC(@OrphanAuditQuestion)


          For this:



          DECLARE @DynamicSQL NVARCHAR(MAX) = N'
          ;WITH PrePivot AS
          (
          SELECT
          Amount = COUNT(*),
          Type = ''OrphanAuditItems''
          FROM
          [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditItems]
          WHERE
          FK_Audit NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[Audits])

          UNION ALL

          SELECT
          Amount = COUNT(*),
          Type = ''OrphanAuditAnswers''
          FROM
          [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditAnswers]
          WHERE
          AuditItemId NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditItems])

          UNION ALL

          SELECT
          Amount = COUNT(*),
          Type = ''OrphanAuditQuestion''
          FROM
          [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditQuestion]
          WHERE
          AuditId NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[Audits])
          )
          SELECT
          P.OrphanAuditItems,
          P.OrphanAuditAnswers,
          P.OrphanAuditQuestion
          FROM
          PrePivot AS T
          PIVOT (
          MAX(T.Amount) FOR T.Type IN ([OrphanAuditItems], [OrphanAuditAnswers], [OrphanAuditQuestion])
          ) AS P '

          -- PRINT (@DynamicSQL)
          EXEC (@DynamicSQL)


          Make sure to use the PRINT to validate the resulting SQL before executing the EXEC.





          Another solution is to retrieve the values into variables, using sp_executesql with OUTPUT parameters:



          -- Items
          DECLARE @OrphanAuditItems INT

          DECLARE @DynamicSQL NVARCHAR(MAX) = N'
          SELECT
          @OrphanAuditItems = COUNT(*)
          FROM
          #OrphanResults AS O
          CROSS JOIN [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditItems]
          WHERE
          FK_Audit NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[Audits])'

          EXEC sp_executesql
          @stmt = @DynamicSQL,
          @params = N'@OrphanAuditItems INT OUTPUT',
          @OrphanAuditItems = @OrphanAuditItems OUTPUT


          -- Answers
          DECLARE @OrphanAuditAnswers INT

          SET @DynamicSQL = N'
          SELECT
          @OrphanAuditAnswers = COUNT(*)
          FROM
          [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditAnswers]
          WHERE
          AuditItemId NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditItems])'

          EXEC sp_executesql
          @stmt = @DynamicSQL,
          @params = N'@OrphanAuditAnswers INT OUTPUT',
          @OrphanAuditAnswers = @OrphanAuditAnswers OUTPUT


          -- Questions
          DECLARE @OrphanAuditQuestion INT

          SET @DynamicSQL = N'
          SELECT
          @OrphanAuditQuestion = COUNT(*)
          FROM
          [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditQuestion]
          WHERE
          AuditId NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[Audits])'

          EXEC sp_executesql
          @stmt = @DynamicSQL,
          @params = N'@OrphanAuditQuestion INT OUTPUT',
          @OrphanAuditQuestion = @OrphanAuditQuestion OUTPUT

          SELECT
          OrphanAuditItems = @OrphanAuditItems,
          OrphanAuditAnswers = @OrphanAuditAnswers,
          OrphanAuditQuestion = @OrphanAuditQuestion


          I find the latter a bit more flexible and readable than the first.






          share|improve this answer


























          • Amazing, thank you so much for this EZLo! I have to admit that I have never seen this type of code before as I'm still learning, but this is working perfectly.

            – Tom_W
            16 hours ago



















          2














          One method is with subqueries for each column. The example below also uses QUOTENAME to enclose identifiers. Personally, I would name schemas as to conform to regular identifier naming rules rather than using the numeric TenantId as the schema name.



          IF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'DetectOrphanDataBeforeUpgrade')
          DROP PROCEDURE [dbo].[DetectOrphanDataBeforeUpgrade]
          GO

          CREATE PROCEDURE [dbo].[DetectOrphanDataBeforeUpgrade]

          @TenantId INT = NULL

          AS
          BEGIN

          DECLARE @OrphanAuditData NVARCHAR(MAX)

          ------------------------------------------------------------------------------------------------
          /* Throw an error if the TenantId is NULL or Invalid. */
          ------------------------------------------------------------------------------------------------
          IF @TenantId IS NULL OR @TenantId NOT IN (SELECT Tenants FROM [Application].[dbo].[TenantIdNumber])
          BEGIN
          THROW 51000, '@TenantId is invalid because it is NULL or does not exist.', 1;
          END


          ------------------------------------------------------------------------------------------------
          /* Checks for Orphan records related to the Audits table */
          ------------------------------------------------------------------------------------------------
          SET @OrphanAuditData = N'SELECT
          (SELECT COUNT(*)
          FROM [Dynamic].' + QUOTENAME(CAST(@TenantId AS NVARCHAR)) + '.[AuditItems]
          WHERE FK_Audit NOT IN (SELECT SystemID FROM [Dynamic].' + QUOTENAME(CAST(@TenantId AS NVARCHAR)) + '.[Audits])) AS OrphanAuditItems
          '
          + N' ,(SELECT COUNT(*)
          FROM [Dynamic].'+ QUOTENAME(CAST(@TenantId AS NVARCHAR)) + '.[AuditAnswers]
          WHERE AuditItemId NOT IN (SELECT SystemID FROM [Dynamic].' + QUOTENAME(CAST(@TenantId AS NVARCHAR)) + '.[AuditItems])) AS OrphanAuditAnswers
          '
          + N' ,(SELECT COUNT(*)
          FROM [Dynamic].'+ QUOTENAME(CAST(@TenantId AS NVARCHAR)) + '.[AuditQuestion]
          WHERE AuditId NOT IN (SELECT SystemID FROM [Dynamic].'+ QUOTENAME(CAST(@TenantId AS NVARCHAR)) + '].[Audits])) AS OrphanAuditQuestion;'

          EXEC (@OrphanAuditData);

          END;
          GO





          share|improve this answer































            0














            I would personally insert all of the data into a holding table in the form of ([COUNT] INT NOT NULL, [TableName] NVARCHAR(MAX) NOT NULL) as below. You can then use PIVOT as below to get the values for each table.



            As an aside, please also note the use of the QUOTENAME function - this will ensure your code isn't vulnerable to SQL injection if the table is passed in as a variable (I would look to simply provide a list of table names and have it run through them all dynamically personally - happy to write this out and provide as an answer if you'd like).



            CREATE TABLE #Datas (ID INT);

            INSERT INTO #Datas
            (
            ID
            )
            VALUES
            ( 1 -- ID - int
            )
            GO

            DECLARE @SQL1 NVARCHAR(MAX) = 'SELECT COUNT(1), ''TableName1'' FROM ' + QUOTENAME('#Datas') + ';'
            DECLARE @SQL2 NVARCHAR(MAX) = 'SELECT COUNT(1), ''TableName2'' FROM ' + QUOTENAME('#Datas') + ';'
            DECLARE @SQL3 NVARCHAR(MAX) = 'SELECT COUNT(1), ''TableName3'' FROM ' + QUOTENAME('#Datas') + ';'

            CREATE TABLE #Counts (Cnt INT, Tbl NVARCHAR(MAX));

            INSERT INTO #Counts
            EXEC (@SQL1);

            INSERT INTO #Counts
            EXEC (@SQL2);

            INSERT INTO #Counts
            EXEC (@SQL3);

            SELECT * FROM #Counts

            PIVOT (SUM(Cnt) FOR Tbl IN ([TableName1],[TableName2],[TableName3])) AS d

            DROP TABLE #Datas;
            DROP TABLE #Counts


            dbfiddle repro






            share|improve this answer































              0














              If you're using SQL Server 2012 or later, you can also just use WITH RESULT SETS with your EXEC:



              exec (N'select 1') 
              WITH RESULT SETS
              (
              (
              ID int
              )
              )


              Result Set






              share|improve this answer























                Your Answer








                StackExchange.ready(function() {
                var channelOptions = {
                tags: "".split(" "),
                id: "182"
                };
                initTagRenderer("".split(" "), "".split(" "), channelOptions);

                StackExchange.using("externalEditor", function() {
                // Have to fire editor after snippets, if snippets enabled
                if (StackExchange.settings.snippets.snippetsEnabled) {
                StackExchange.using("snippets", function() {
                createEditor();
                });
                }
                else {
                createEditor();
                }
                });

                function createEditor() {
                StackExchange.prepareEditor({
                heartbeatType: 'answer',
                autoActivateHeartbeat: false,
                convertImagesToLinks: false,
                noModals: true,
                showLowRepImageUploadWarning: true,
                reputationToPostImages: null,
                bindNavPrevention: true,
                postfix: "",
                imageUploader: {
                brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
                contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
                allowUrls: true
                },
                onDemand: true,
                discardSelector: ".discard-answer"
                ,immediatelyShowMarkdownHelp:true
                });


                }
                });














                draft saved

                draft discarded


















                StackExchange.ready(
                function () {
                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f232238%2fgiving-exec-variable-a-column-name-and-concatenation%23new-answer', 'question_page');
                }
                );

                Post as a guest















                Required, but never shown

























                4 Answers
                4






                active

                oldest

                votes








                4 Answers
                4






                active

                oldest

                votes









                active

                oldest

                votes






                active

                oldest

                votes









                3














                You will need to mix your 3 dynamic SQLs into 1 that returns 3 columns, or keep each dynamic SQL but mix their result at the end. There are 2 possible solutions following:





                One solution is to use UNION ALL and the PIVOT to get 1 row with 3 columns, all inside the dynamic SQL.



                Change this part:



                DECLARE @OrphanAuditItems NVARCHAR(MAX)
                DECLARE @OrphanAuditAnswers NVARCHAR(MAX)
                DECLARE @OrphanAuditQuestion NVARCHAR(MAX)

                --.....

                SET @OrphanAuditItems = N'SELECT COUNT(*) FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditItems]
                WHERE FK_Audit NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[Audits])'

                SET @OrphanAuditAnswers = N'SELECT COUNT(*) FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditAnswers]
                WHERE AuditItemId NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditItems])'

                SET @OrphanAuditQuestion = N'SELECT COUNT(*) FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditQuestion]
                WHERE AuditId NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[Audits])'

                EXEC (@OrphanAuditItems)
                EXEC(@OrphanAuditAnswers)
                EXEC(@OrphanAuditQuestion)


                For this:



                DECLARE @DynamicSQL NVARCHAR(MAX) = N'
                ;WITH PrePivot AS
                (
                SELECT
                Amount = COUNT(*),
                Type = ''OrphanAuditItems''
                FROM
                [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditItems]
                WHERE
                FK_Audit NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[Audits])

                UNION ALL

                SELECT
                Amount = COUNT(*),
                Type = ''OrphanAuditAnswers''
                FROM
                [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditAnswers]
                WHERE
                AuditItemId NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditItems])

                UNION ALL

                SELECT
                Amount = COUNT(*),
                Type = ''OrphanAuditQuestion''
                FROM
                [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditQuestion]
                WHERE
                AuditId NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[Audits])
                )
                SELECT
                P.OrphanAuditItems,
                P.OrphanAuditAnswers,
                P.OrphanAuditQuestion
                FROM
                PrePivot AS T
                PIVOT (
                MAX(T.Amount) FOR T.Type IN ([OrphanAuditItems], [OrphanAuditAnswers], [OrphanAuditQuestion])
                ) AS P '

                -- PRINT (@DynamicSQL)
                EXEC (@DynamicSQL)


                Make sure to use the PRINT to validate the resulting SQL before executing the EXEC.





                Another solution is to retrieve the values into variables, using sp_executesql with OUTPUT parameters:



                -- Items
                DECLARE @OrphanAuditItems INT

                DECLARE @DynamicSQL NVARCHAR(MAX) = N'
                SELECT
                @OrphanAuditItems = COUNT(*)
                FROM
                #OrphanResults AS O
                CROSS JOIN [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditItems]
                WHERE
                FK_Audit NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[Audits])'

                EXEC sp_executesql
                @stmt = @DynamicSQL,
                @params = N'@OrphanAuditItems INT OUTPUT',
                @OrphanAuditItems = @OrphanAuditItems OUTPUT


                -- Answers
                DECLARE @OrphanAuditAnswers INT

                SET @DynamicSQL = N'
                SELECT
                @OrphanAuditAnswers = COUNT(*)
                FROM
                [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditAnswers]
                WHERE
                AuditItemId NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditItems])'

                EXEC sp_executesql
                @stmt = @DynamicSQL,
                @params = N'@OrphanAuditAnswers INT OUTPUT',
                @OrphanAuditAnswers = @OrphanAuditAnswers OUTPUT


                -- Questions
                DECLARE @OrphanAuditQuestion INT

                SET @DynamicSQL = N'
                SELECT
                @OrphanAuditQuestion = COUNT(*)
                FROM
                [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditQuestion]
                WHERE
                AuditId NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[Audits])'

                EXEC sp_executesql
                @stmt = @DynamicSQL,
                @params = N'@OrphanAuditQuestion INT OUTPUT',
                @OrphanAuditQuestion = @OrphanAuditQuestion OUTPUT

                SELECT
                OrphanAuditItems = @OrphanAuditItems,
                OrphanAuditAnswers = @OrphanAuditAnswers,
                OrphanAuditQuestion = @OrphanAuditQuestion


                I find the latter a bit more flexible and readable than the first.






                share|improve this answer


























                • Amazing, thank you so much for this EZLo! I have to admit that I have never seen this type of code before as I'm still learning, but this is working perfectly.

                  – Tom_W
                  16 hours ago
















                3














                You will need to mix your 3 dynamic SQLs into 1 that returns 3 columns, or keep each dynamic SQL but mix their result at the end. There are 2 possible solutions following:





                One solution is to use UNION ALL and the PIVOT to get 1 row with 3 columns, all inside the dynamic SQL.



                Change this part:



                DECLARE @OrphanAuditItems NVARCHAR(MAX)
                DECLARE @OrphanAuditAnswers NVARCHAR(MAX)
                DECLARE @OrphanAuditQuestion NVARCHAR(MAX)

                --.....

                SET @OrphanAuditItems = N'SELECT COUNT(*) FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditItems]
                WHERE FK_Audit NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[Audits])'

                SET @OrphanAuditAnswers = N'SELECT COUNT(*) FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditAnswers]
                WHERE AuditItemId NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditItems])'

                SET @OrphanAuditQuestion = N'SELECT COUNT(*) FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditQuestion]
                WHERE AuditId NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[Audits])'

                EXEC (@OrphanAuditItems)
                EXEC(@OrphanAuditAnswers)
                EXEC(@OrphanAuditQuestion)


                For this:



                DECLARE @DynamicSQL NVARCHAR(MAX) = N'
                ;WITH PrePivot AS
                (
                SELECT
                Amount = COUNT(*),
                Type = ''OrphanAuditItems''
                FROM
                [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditItems]
                WHERE
                FK_Audit NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[Audits])

                UNION ALL

                SELECT
                Amount = COUNT(*),
                Type = ''OrphanAuditAnswers''
                FROM
                [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditAnswers]
                WHERE
                AuditItemId NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditItems])

                UNION ALL

                SELECT
                Amount = COUNT(*),
                Type = ''OrphanAuditQuestion''
                FROM
                [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditQuestion]
                WHERE
                AuditId NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[Audits])
                )
                SELECT
                P.OrphanAuditItems,
                P.OrphanAuditAnswers,
                P.OrphanAuditQuestion
                FROM
                PrePivot AS T
                PIVOT (
                MAX(T.Amount) FOR T.Type IN ([OrphanAuditItems], [OrphanAuditAnswers], [OrphanAuditQuestion])
                ) AS P '

                -- PRINT (@DynamicSQL)
                EXEC (@DynamicSQL)


                Make sure to use the PRINT to validate the resulting SQL before executing the EXEC.





                Another solution is to retrieve the values into variables, using sp_executesql with OUTPUT parameters:



                -- Items
                DECLARE @OrphanAuditItems INT

                DECLARE @DynamicSQL NVARCHAR(MAX) = N'
                SELECT
                @OrphanAuditItems = COUNT(*)
                FROM
                #OrphanResults AS O
                CROSS JOIN [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditItems]
                WHERE
                FK_Audit NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[Audits])'

                EXEC sp_executesql
                @stmt = @DynamicSQL,
                @params = N'@OrphanAuditItems INT OUTPUT',
                @OrphanAuditItems = @OrphanAuditItems OUTPUT


                -- Answers
                DECLARE @OrphanAuditAnswers INT

                SET @DynamicSQL = N'
                SELECT
                @OrphanAuditAnswers = COUNT(*)
                FROM
                [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditAnswers]
                WHERE
                AuditItemId NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditItems])'

                EXEC sp_executesql
                @stmt = @DynamicSQL,
                @params = N'@OrphanAuditAnswers INT OUTPUT',
                @OrphanAuditAnswers = @OrphanAuditAnswers OUTPUT


                -- Questions
                DECLARE @OrphanAuditQuestion INT

                SET @DynamicSQL = N'
                SELECT
                @OrphanAuditQuestion = COUNT(*)
                FROM
                [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditQuestion]
                WHERE
                AuditId NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[Audits])'

                EXEC sp_executesql
                @stmt = @DynamicSQL,
                @params = N'@OrphanAuditQuestion INT OUTPUT',
                @OrphanAuditQuestion = @OrphanAuditQuestion OUTPUT

                SELECT
                OrphanAuditItems = @OrphanAuditItems,
                OrphanAuditAnswers = @OrphanAuditAnswers,
                OrphanAuditQuestion = @OrphanAuditQuestion


                I find the latter a bit more flexible and readable than the first.






                share|improve this answer


























                • Amazing, thank you so much for this EZLo! I have to admit that I have never seen this type of code before as I'm still learning, but this is working perfectly.

                  – Tom_W
                  16 hours ago














                3












                3








                3







                You will need to mix your 3 dynamic SQLs into 1 that returns 3 columns, or keep each dynamic SQL but mix their result at the end. There are 2 possible solutions following:





                One solution is to use UNION ALL and the PIVOT to get 1 row with 3 columns, all inside the dynamic SQL.



                Change this part:



                DECLARE @OrphanAuditItems NVARCHAR(MAX)
                DECLARE @OrphanAuditAnswers NVARCHAR(MAX)
                DECLARE @OrphanAuditQuestion NVARCHAR(MAX)

                --.....

                SET @OrphanAuditItems = N'SELECT COUNT(*) FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditItems]
                WHERE FK_Audit NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[Audits])'

                SET @OrphanAuditAnswers = N'SELECT COUNT(*) FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditAnswers]
                WHERE AuditItemId NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditItems])'

                SET @OrphanAuditQuestion = N'SELECT COUNT(*) FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditQuestion]
                WHERE AuditId NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[Audits])'

                EXEC (@OrphanAuditItems)
                EXEC(@OrphanAuditAnswers)
                EXEC(@OrphanAuditQuestion)


                For this:



                DECLARE @DynamicSQL NVARCHAR(MAX) = N'
                ;WITH PrePivot AS
                (
                SELECT
                Amount = COUNT(*),
                Type = ''OrphanAuditItems''
                FROM
                [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditItems]
                WHERE
                FK_Audit NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[Audits])

                UNION ALL

                SELECT
                Amount = COUNT(*),
                Type = ''OrphanAuditAnswers''
                FROM
                [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditAnswers]
                WHERE
                AuditItemId NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditItems])

                UNION ALL

                SELECT
                Amount = COUNT(*),
                Type = ''OrphanAuditQuestion''
                FROM
                [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditQuestion]
                WHERE
                AuditId NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[Audits])
                )
                SELECT
                P.OrphanAuditItems,
                P.OrphanAuditAnswers,
                P.OrphanAuditQuestion
                FROM
                PrePivot AS T
                PIVOT (
                MAX(T.Amount) FOR T.Type IN ([OrphanAuditItems], [OrphanAuditAnswers], [OrphanAuditQuestion])
                ) AS P '

                -- PRINT (@DynamicSQL)
                EXEC (@DynamicSQL)


                Make sure to use the PRINT to validate the resulting SQL before executing the EXEC.





                Another solution is to retrieve the values into variables, using sp_executesql with OUTPUT parameters:



                -- Items
                DECLARE @OrphanAuditItems INT

                DECLARE @DynamicSQL NVARCHAR(MAX) = N'
                SELECT
                @OrphanAuditItems = COUNT(*)
                FROM
                #OrphanResults AS O
                CROSS JOIN [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditItems]
                WHERE
                FK_Audit NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[Audits])'

                EXEC sp_executesql
                @stmt = @DynamicSQL,
                @params = N'@OrphanAuditItems INT OUTPUT',
                @OrphanAuditItems = @OrphanAuditItems OUTPUT


                -- Answers
                DECLARE @OrphanAuditAnswers INT

                SET @DynamicSQL = N'
                SELECT
                @OrphanAuditAnswers = COUNT(*)
                FROM
                [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditAnswers]
                WHERE
                AuditItemId NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditItems])'

                EXEC sp_executesql
                @stmt = @DynamicSQL,
                @params = N'@OrphanAuditAnswers INT OUTPUT',
                @OrphanAuditAnswers = @OrphanAuditAnswers OUTPUT


                -- Questions
                DECLARE @OrphanAuditQuestion INT

                SET @DynamicSQL = N'
                SELECT
                @OrphanAuditQuestion = COUNT(*)
                FROM
                [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditQuestion]
                WHERE
                AuditId NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[Audits])'

                EXEC sp_executesql
                @stmt = @DynamicSQL,
                @params = N'@OrphanAuditQuestion INT OUTPUT',
                @OrphanAuditQuestion = @OrphanAuditQuestion OUTPUT

                SELECT
                OrphanAuditItems = @OrphanAuditItems,
                OrphanAuditAnswers = @OrphanAuditAnswers,
                OrphanAuditQuestion = @OrphanAuditQuestion


                I find the latter a bit more flexible and readable than the first.






                share|improve this answer















                You will need to mix your 3 dynamic SQLs into 1 that returns 3 columns, or keep each dynamic SQL but mix their result at the end. There are 2 possible solutions following:





                One solution is to use UNION ALL and the PIVOT to get 1 row with 3 columns, all inside the dynamic SQL.



                Change this part:



                DECLARE @OrphanAuditItems NVARCHAR(MAX)
                DECLARE @OrphanAuditAnswers NVARCHAR(MAX)
                DECLARE @OrphanAuditQuestion NVARCHAR(MAX)

                --.....

                SET @OrphanAuditItems = N'SELECT COUNT(*) FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditItems]
                WHERE FK_Audit NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[Audits])'

                SET @OrphanAuditAnswers = N'SELECT COUNT(*) FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditAnswers]
                WHERE AuditItemId NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditItems])'

                SET @OrphanAuditQuestion = N'SELECT COUNT(*) FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditQuestion]
                WHERE AuditId NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[Audits])'

                EXEC (@OrphanAuditItems)
                EXEC(@OrphanAuditAnswers)
                EXEC(@OrphanAuditQuestion)


                For this:



                DECLARE @DynamicSQL NVARCHAR(MAX) = N'
                ;WITH PrePivot AS
                (
                SELECT
                Amount = COUNT(*),
                Type = ''OrphanAuditItems''
                FROM
                [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditItems]
                WHERE
                FK_Audit NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[Audits])

                UNION ALL

                SELECT
                Amount = COUNT(*),
                Type = ''OrphanAuditAnswers''
                FROM
                [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditAnswers]
                WHERE
                AuditItemId NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditItems])

                UNION ALL

                SELECT
                Amount = COUNT(*),
                Type = ''OrphanAuditQuestion''
                FROM
                [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditQuestion]
                WHERE
                AuditId NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[Audits])
                )
                SELECT
                P.OrphanAuditItems,
                P.OrphanAuditAnswers,
                P.OrphanAuditQuestion
                FROM
                PrePivot AS T
                PIVOT (
                MAX(T.Amount) FOR T.Type IN ([OrphanAuditItems], [OrphanAuditAnswers], [OrphanAuditQuestion])
                ) AS P '

                -- PRINT (@DynamicSQL)
                EXEC (@DynamicSQL)


                Make sure to use the PRINT to validate the resulting SQL before executing the EXEC.





                Another solution is to retrieve the values into variables, using sp_executesql with OUTPUT parameters:



                -- Items
                DECLARE @OrphanAuditItems INT

                DECLARE @DynamicSQL NVARCHAR(MAX) = N'
                SELECT
                @OrphanAuditItems = COUNT(*)
                FROM
                #OrphanResults AS O
                CROSS JOIN [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditItems]
                WHERE
                FK_Audit NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[Audits])'

                EXEC sp_executesql
                @stmt = @DynamicSQL,
                @params = N'@OrphanAuditItems INT OUTPUT',
                @OrphanAuditItems = @OrphanAuditItems OUTPUT


                -- Answers
                DECLARE @OrphanAuditAnswers INT

                SET @DynamicSQL = N'
                SELECT
                @OrphanAuditAnswers = COUNT(*)
                FROM
                [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditAnswers]
                WHERE
                AuditItemId NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditItems])'

                EXEC sp_executesql
                @stmt = @DynamicSQL,
                @params = N'@OrphanAuditAnswers INT OUTPUT',
                @OrphanAuditAnswers = @OrphanAuditAnswers OUTPUT


                -- Questions
                DECLARE @OrphanAuditQuestion INT

                SET @DynamicSQL = N'
                SELECT
                @OrphanAuditQuestion = COUNT(*)
                FROM
                [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[AuditQuestion]
                WHERE
                AuditId NOT IN (SELECT SystemID FROM [Dynamic].['+ CAST (@TenantId AS NVARCHAR) +'].[Audits])'

                EXEC sp_executesql
                @stmt = @DynamicSQL,
                @params = N'@OrphanAuditQuestion INT OUTPUT',
                @OrphanAuditQuestion = @OrphanAuditQuestion OUTPUT

                SELECT
                OrphanAuditItems = @OrphanAuditItems,
                OrphanAuditAnswers = @OrphanAuditAnswers,
                OrphanAuditQuestion = @OrphanAuditQuestion


                I find the latter a bit more flexible and readable than the first.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited 16 hours ago

























                answered 17 hours ago









                EzLoEzLo

                2,5291521




                2,5291521













                • Amazing, thank you so much for this EZLo! I have to admit that I have never seen this type of code before as I'm still learning, but this is working perfectly.

                  – Tom_W
                  16 hours ago



















                • Amazing, thank you so much for this EZLo! I have to admit that I have never seen this type of code before as I'm still learning, but this is working perfectly.

                  – Tom_W
                  16 hours ago

















                Amazing, thank you so much for this EZLo! I have to admit that I have never seen this type of code before as I'm still learning, but this is working perfectly.

                – Tom_W
                16 hours ago





                Amazing, thank you so much for this EZLo! I have to admit that I have never seen this type of code before as I'm still learning, but this is working perfectly.

                – Tom_W
                16 hours ago













                2














                One method is with subqueries for each column. The example below also uses QUOTENAME to enclose identifiers. Personally, I would name schemas as to conform to regular identifier naming rules rather than using the numeric TenantId as the schema name.



                IF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'DetectOrphanDataBeforeUpgrade')
                DROP PROCEDURE [dbo].[DetectOrphanDataBeforeUpgrade]
                GO

                CREATE PROCEDURE [dbo].[DetectOrphanDataBeforeUpgrade]

                @TenantId INT = NULL

                AS
                BEGIN

                DECLARE @OrphanAuditData NVARCHAR(MAX)

                ------------------------------------------------------------------------------------------------
                /* Throw an error if the TenantId is NULL or Invalid. */
                ------------------------------------------------------------------------------------------------
                IF @TenantId IS NULL OR @TenantId NOT IN (SELECT Tenants FROM [Application].[dbo].[TenantIdNumber])
                BEGIN
                THROW 51000, '@TenantId is invalid because it is NULL or does not exist.', 1;
                END


                ------------------------------------------------------------------------------------------------
                /* Checks for Orphan records related to the Audits table */
                ------------------------------------------------------------------------------------------------
                SET @OrphanAuditData = N'SELECT
                (SELECT COUNT(*)
                FROM [Dynamic].' + QUOTENAME(CAST(@TenantId AS NVARCHAR)) + '.[AuditItems]
                WHERE FK_Audit NOT IN (SELECT SystemID FROM [Dynamic].' + QUOTENAME(CAST(@TenantId AS NVARCHAR)) + '.[Audits])) AS OrphanAuditItems
                '
                + N' ,(SELECT COUNT(*)
                FROM [Dynamic].'+ QUOTENAME(CAST(@TenantId AS NVARCHAR)) + '.[AuditAnswers]
                WHERE AuditItemId NOT IN (SELECT SystemID FROM [Dynamic].' + QUOTENAME(CAST(@TenantId AS NVARCHAR)) + '.[AuditItems])) AS OrphanAuditAnswers
                '
                + N' ,(SELECT COUNT(*)
                FROM [Dynamic].'+ QUOTENAME(CAST(@TenantId AS NVARCHAR)) + '.[AuditQuestion]
                WHERE AuditId NOT IN (SELECT SystemID FROM [Dynamic].'+ QUOTENAME(CAST(@TenantId AS NVARCHAR)) + '].[Audits])) AS OrphanAuditQuestion;'

                EXEC (@OrphanAuditData);

                END;
                GO





                share|improve this answer




























                  2














                  One method is with subqueries for each column. The example below also uses QUOTENAME to enclose identifiers. Personally, I would name schemas as to conform to regular identifier naming rules rather than using the numeric TenantId as the schema name.



                  IF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'DetectOrphanDataBeforeUpgrade')
                  DROP PROCEDURE [dbo].[DetectOrphanDataBeforeUpgrade]
                  GO

                  CREATE PROCEDURE [dbo].[DetectOrphanDataBeforeUpgrade]

                  @TenantId INT = NULL

                  AS
                  BEGIN

                  DECLARE @OrphanAuditData NVARCHAR(MAX)

                  ------------------------------------------------------------------------------------------------
                  /* Throw an error if the TenantId is NULL or Invalid. */
                  ------------------------------------------------------------------------------------------------
                  IF @TenantId IS NULL OR @TenantId NOT IN (SELECT Tenants FROM [Application].[dbo].[TenantIdNumber])
                  BEGIN
                  THROW 51000, '@TenantId is invalid because it is NULL or does not exist.', 1;
                  END


                  ------------------------------------------------------------------------------------------------
                  /* Checks for Orphan records related to the Audits table */
                  ------------------------------------------------------------------------------------------------
                  SET @OrphanAuditData = N'SELECT
                  (SELECT COUNT(*)
                  FROM [Dynamic].' + QUOTENAME(CAST(@TenantId AS NVARCHAR)) + '.[AuditItems]
                  WHERE FK_Audit NOT IN (SELECT SystemID FROM [Dynamic].' + QUOTENAME(CAST(@TenantId AS NVARCHAR)) + '.[Audits])) AS OrphanAuditItems
                  '
                  + N' ,(SELECT COUNT(*)
                  FROM [Dynamic].'+ QUOTENAME(CAST(@TenantId AS NVARCHAR)) + '.[AuditAnswers]
                  WHERE AuditItemId NOT IN (SELECT SystemID FROM [Dynamic].' + QUOTENAME(CAST(@TenantId AS NVARCHAR)) + '.[AuditItems])) AS OrphanAuditAnswers
                  '
                  + N' ,(SELECT COUNT(*)
                  FROM [Dynamic].'+ QUOTENAME(CAST(@TenantId AS NVARCHAR)) + '.[AuditQuestion]
                  WHERE AuditId NOT IN (SELECT SystemID FROM [Dynamic].'+ QUOTENAME(CAST(@TenantId AS NVARCHAR)) + '].[Audits])) AS OrphanAuditQuestion;'

                  EXEC (@OrphanAuditData);

                  END;
                  GO





                  share|improve this answer


























                    2












                    2








                    2







                    One method is with subqueries for each column. The example below also uses QUOTENAME to enclose identifiers. Personally, I would name schemas as to conform to regular identifier naming rules rather than using the numeric TenantId as the schema name.



                    IF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'DetectOrphanDataBeforeUpgrade')
                    DROP PROCEDURE [dbo].[DetectOrphanDataBeforeUpgrade]
                    GO

                    CREATE PROCEDURE [dbo].[DetectOrphanDataBeforeUpgrade]

                    @TenantId INT = NULL

                    AS
                    BEGIN

                    DECLARE @OrphanAuditData NVARCHAR(MAX)

                    ------------------------------------------------------------------------------------------------
                    /* Throw an error if the TenantId is NULL or Invalid. */
                    ------------------------------------------------------------------------------------------------
                    IF @TenantId IS NULL OR @TenantId NOT IN (SELECT Tenants FROM [Application].[dbo].[TenantIdNumber])
                    BEGIN
                    THROW 51000, '@TenantId is invalid because it is NULL or does not exist.', 1;
                    END


                    ------------------------------------------------------------------------------------------------
                    /* Checks for Orphan records related to the Audits table */
                    ------------------------------------------------------------------------------------------------
                    SET @OrphanAuditData = N'SELECT
                    (SELECT COUNT(*)
                    FROM [Dynamic].' + QUOTENAME(CAST(@TenantId AS NVARCHAR)) + '.[AuditItems]
                    WHERE FK_Audit NOT IN (SELECT SystemID FROM [Dynamic].' + QUOTENAME(CAST(@TenantId AS NVARCHAR)) + '.[Audits])) AS OrphanAuditItems
                    '
                    + N' ,(SELECT COUNT(*)
                    FROM [Dynamic].'+ QUOTENAME(CAST(@TenantId AS NVARCHAR)) + '.[AuditAnswers]
                    WHERE AuditItemId NOT IN (SELECT SystemID FROM [Dynamic].' + QUOTENAME(CAST(@TenantId AS NVARCHAR)) + '.[AuditItems])) AS OrphanAuditAnswers
                    '
                    + N' ,(SELECT COUNT(*)
                    FROM [Dynamic].'+ QUOTENAME(CAST(@TenantId AS NVARCHAR)) + '.[AuditQuestion]
                    WHERE AuditId NOT IN (SELECT SystemID FROM [Dynamic].'+ QUOTENAME(CAST(@TenantId AS NVARCHAR)) + '].[Audits])) AS OrphanAuditQuestion;'

                    EXEC (@OrphanAuditData);

                    END;
                    GO





                    share|improve this answer













                    One method is with subqueries for each column. The example below also uses QUOTENAME to enclose identifiers. Personally, I would name schemas as to conform to regular identifier naming rules rather than using the numeric TenantId as the schema name.



                    IF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'DetectOrphanDataBeforeUpgrade')
                    DROP PROCEDURE [dbo].[DetectOrphanDataBeforeUpgrade]
                    GO

                    CREATE PROCEDURE [dbo].[DetectOrphanDataBeforeUpgrade]

                    @TenantId INT = NULL

                    AS
                    BEGIN

                    DECLARE @OrphanAuditData NVARCHAR(MAX)

                    ------------------------------------------------------------------------------------------------
                    /* Throw an error if the TenantId is NULL or Invalid. */
                    ------------------------------------------------------------------------------------------------
                    IF @TenantId IS NULL OR @TenantId NOT IN (SELECT Tenants FROM [Application].[dbo].[TenantIdNumber])
                    BEGIN
                    THROW 51000, '@TenantId is invalid because it is NULL or does not exist.', 1;
                    END


                    ------------------------------------------------------------------------------------------------
                    /* Checks for Orphan records related to the Audits table */
                    ------------------------------------------------------------------------------------------------
                    SET @OrphanAuditData = N'SELECT
                    (SELECT COUNT(*)
                    FROM [Dynamic].' + QUOTENAME(CAST(@TenantId AS NVARCHAR)) + '.[AuditItems]
                    WHERE FK_Audit NOT IN (SELECT SystemID FROM [Dynamic].' + QUOTENAME(CAST(@TenantId AS NVARCHAR)) + '.[Audits])) AS OrphanAuditItems
                    '
                    + N' ,(SELECT COUNT(*)
                    FROM [Dynamic].'+ QUOTENAME(CAST(@TenantId AS NVARCHAR)) + '.[AuditAnswers]
                    WHERE AuditItemId NOT IN (SELECT SystemID FROM [Dynamic].' + QUOTENAME(CAST(@TenantId AS NVARCHAR)) + '.[AuditItems])) AS OrphanAuditAnswers
                    '
                    + N' ,(SELECT COUNT(*)
                    FROM [Dynamic].'+ QUOTENAME(CAST(@TenantId AS NVARCHAR)) + '.[AuditQuestion]
                    WHERE AuditId NOT IN (SELECT SystemID FROM [Dynamic].'+ QUOTENAME(CAST(@TenantId AS NVARCHAR)) + '].[Audits])) AS OrphanAuditQuestion;'

                    EXEC (@OrphanAuditData);

                    END;
                    GO






                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered 17 hours ago









                    Dan GuzmanDan Guzman

                    14k21735




                    14k21735























                        0














                        I would personally insert all of the data into a holding table in the form of ([COUNT] INT NOT NULL, [TableName] NVARCHAR(MAX) NOT NULL) as below. You can then use PIVOT as below to get the values for each table.



                        As an aside, please also note the use of the QUOTENAME function - this will ensure your code isn't vulnerable to SQL injection if the table is passed in as a variable (I would look to simply provide a list of table names and have it run through them all dynamically personally - happy to write this out and provide as an answer if you'd like).



                        CREATE TABLE #Datas (ID INT);

                        INSERT INTO #Datas
                        (
                        ID
                        )
                        VALUES
                        ( 1 -- ID - int
                        )
                        GO

                        DECLARE @SQL1 NVARCHAR(MAX) = 'SELECT COUNT(1), ''TableName1'' FROM ' + QUOTENAME('#Datas') + ';'
                        DECLARE @SQL2 NVARCHAR(MAX) = 'SELECT COUNT(1), ''TableName2'' FROM ' + QUOTENAME('#Datas') + ';'
                        DECLARE @SQL3 NVARCHAR(MAX) = 'SELECT COUNT(1), ''TableName3'' FROM ' + QUOTENAME('#Datas') + ';'

                        CREATE TABLE #Counts (Cnt INT, Tbl NVARCHAR(MAX));

                        INSERT INTO #Counts
                        EXEC (@SQL1);

                        INSERT INTO #Counts
                        EXEC (@SQL2);

                        INSERT INTO #Counts
                        EXEC (@SQL3);

                        SELECT * FROM #Counts

                        PIVOT (SUM(Cnt) FOR Tbl IN ([TableName1],[TableName2],[TableName3])) AS d

                        DROP TABLE #Datas;
                        DROP TABLE #Counts


                        dbfiddle repro






                        share|improve this answer




























                          0














                          I would personally insert all of the data into a holding table in the form of ([COUNT] INT NOT NULL, [TableName] NVARCHAR(MAX) NOT NULL) as below. You can then use PIVOT as below to get the values for each table.



                          As an aside, please also note the use of the QUOTENAME function - this will ensure your code isn't vulnerable to SQL injection if the table is passed in as a variable (I would look to simply provide a list of table names and have it run through them all dynamically personally - happy to write this out and provide as an answer if you'd like).



                          CREATE TABLE #Datas (ID INT);

                          INSERT INTO #Datas
                          (
                          ID
                          )
                          VALUES
                          ( 1 -- ID - int
                          )
                          GO

                          DECLARE @SQL1 NVARCHAR(MAX) = 'SELECT COUNT(1), ''TableName1'' FROM ' + QUOTENAME('#Datas') + ';'
                          DECLARE @SQL2 NVARCHAR(MAX) = 'SELECT COUNT(1), ''TableName2'' FROM ' + QUOTENAME('#Datas') + ';'
                          DECLARE @SQL3 NVARCHAR(MAX) = 'SELECT COUNT(1), ''TableName3'' FROM ' + QUOTENAME('#Datas') + ';'

                          CREATE TABLE #Counts (Cnt INT, Tbl NVARCHAR(MAX));

                          INSERT INTO #Counts
                          EXEC (@SQL1);

                          INSERT INTO #Counts
                          EXEC (@SQL2);

                          INSERT INTO #Counts
                          EXEC (@SQL3);

                          SELECT * FROM #Counts

                          PIVOT (SUM(Cnt) FOR Tbl IN ([TableName1],[TableName2],[TableName3])) AS d

                          DROP TABLE #Datas;
                          DROP TABLE #Counts


                          dbfiddle repro






                          share|improve this answer


























                            0












                            0








                            0







                            I would personally insert all of the data into a holding table in the form of ([COUNT] INT NOT NULL, [TableName] NVARCHAR(MAX) NOT NULL) as below. You can then use PIVOT as below to get the values for each table.



                            As an aside, please also note the use of the QUOTENAME function - this will ensure your code isn't vulnerable to SQL injection if the table is passed in as a variable (I would look to simply provide a list of table names and have it run through them all dynamically personally - happy to write this out and provide as an answer if you'd like).



                            CREATE TABLE #Datas (ID INT);

                            INSERT INTO #Datas
                            (
                            ID
                            )
                            VALUES
                            ( 1 -- ID - int
                            )
                            GO

                            DECLARE @SQL1 NVARCHAR(MAX) = 'SELECT COUNT(1), ''TableName1'' FROM ' + QUOTENAME('#Datas') + ';'
                            DECLARE @SQL2 NVARCHAR(MAX) = 'SELECT COUNT(1), ''TableName2'' FROM ' + QUOTENAME('#Datas') + ';'
                            DECLARE @SQL3 NVARCHAR(MAX) = 'SELECT COUNT(1), ''TableName3'' FROM ' + QUOTENAME('#Datas') + ';'

                            CREATE TABLE #Counts (Cnt INT, Tbl NVARCHAR(MAX));

                            INSERT INTO #Counts
                            EXEC (@SQL1);

                            INSERT INTO #Counts
                            EXEC (@SQL2);

                            INSERT INTO #Counts
                            EXEC (@SQL3);

                            SELECT * FROM #Counts

                            PIVOT (SUM(Cnt) FOR Tbl IN ([TableName1],[TableName2],[TableName3])) AS d

                            DROP TABLE #Datas;
                            DROP TABLE #Counts


                            dbfiddle repro






                            share|improve this answer













                            I would personally insert all of the data into a holding table in the form of ([COUNT] INT NOT NULL, [TableName] NVARCHAR(MAX) NOT NULL) as below. You can then use PIVOT as below to get the values for each table.



                            As an aside, please also note the use of the QUOTENAME function - this will ensure your code isn't vulnerable to SQL injection if the table is passed in as a variable (I would look to simply provide a list of table names and have it run through them all dynamically personally - happy to write this out and provide as an answer if you'd like).



                            CREATE TABLE #Datas (ID INT);

                            INSERT INTO #Datas
                            (
                            ID
                            )
                            VALUES
                            ( 1 -- ID - int
                            )
                            GO

                            DECLARE @SQL1 NVARCHAR(MAX) = 'SELECT COUNT(1), ''TableName1'' FROM ' + QUOTENAME('#Datas') + ';'
                            DECLARE @SQL2 NVARCHAR(MAX) = 'SELECT COUNT(1), ''TableName2'' FROM ' + QUOTENAME('#Datas') + ';'
                            DECLARE @SQL3 NVARCHAR(MAX) = 'SELECT COUNT(1), ''TableName3'' FROM ' + QUOTENAME('#Datas') + ';'

                            CREATE TABLE #Counts (Cnt INT, Tbl NVARCHAR(MAX));

                            INSERT INTO #Counts
                            EXEC (@SQL1);

                            INSERT INTO #Counts
                            EXEC (@SQL2);

                            INSERT INTO #Counts
                            EXEC (@SQL3);

                            SELECT * FROM #Counts

                            PIVOT (SUM(Cnt) FOR Tbl IN ([TableName1],[TableName2],[TableName3])) AS d

                            DROP TABLE #Datas;
                            DROP TABLE #Counts


                            dbfiddle repro







                            share|improve this answer












                            share|improve this answer



                            share|improve this answer










                            answered 17 hours ago









                            George.PalaciosGeorge.Palacios

                            2,328825




                            2,328825























                                0














                                If you're using SQL Server 2012 or later, you can also just use WITH RESULT SETS with your EXEC:



                                exec (N'select 1') 
                                WITH RESULT SETS
                                (
                                (
                                ID int
                                )
                                )


                                Result Set






                                share|improve this answer




























                                  0














                                  If you're using SQL Server 2012 or later, you can also just use WITH RESULT SETS with your EXEC:



                                  exec (N'select 1') 
                                  WITH RESULT SETS
                                  (
                                  (
                                  ID int
                                  )
                                  )


                                  Result Set






                                  share|improve this answer


























                                    0












                                    0








                                    0







                                    If you're using SQL Server 2012 or later, you can also just use WITH RESULT SETS with your EXEC:



                                    exec (N'select 1') 
                                    WITH RESULT SETS
                                    (
                                    (
                                    ID int
                                    )
                                    )


                                    Result Set






                                    share|improve this answer













                                    If you're using SQL Server 2012 or later, you can also just use WITH RESULT SETS with your EXEC:



                                    exec (N'select 1') 
                                    WITH RESULT SETS
                                    (
                                    (
                                    ID int
                                    )
                                    )


                                    Result Set







                                    share|improve this answer












                                    share|improve this answer



                                    share|improve this answer










                                    answered 8 hours ago









                                    Jason WhitishJason Whitish

                                    1456




                                    1456






























                                        draft saved

                                        draft discarded




















































                                        Thanks for contributing an answer to Database Administrators Stack Exchange!


                                        • Please be sure to answer the question. Provide details and share your research!

                                        But avoid



                                        • Asking for help, clarification, or responding to other answers.

                                        • Making statements based on opinion; back them up with references or personal experience.


                                        To learn more, see our tips on writing great answers.




                                        draft saved


                                        draft discarded














                                        StackExchange.ready(
                                        function () {
                                        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f232238%2fgiving-exec-variable-a-column-name-and-concatenation%23new-answer', 'question_page');
                                        }
                                        );

                                        Post as a guest















                                        Required, but never shown





















































                                        Required, but never shown














                                        Required, but never shown












                                        Required, but never shown







                                        Required, but never shown

































                                        Required, but never shown














                                        Required, but never shown












                                        Required, but never shown







                                        Required, but never shown







                                        Popular posts from this blog

                                        數位音樂下載

                                        格利澤436b

                                        When can things happen in Etherscan, such as the picture below?