Giving EXEC (@Variable) a Column name and ConcatenationSQL SERVER 2008 TVF OR CHARINDEX to search column with commaOracle GoldenGate add trandata errorsDynamic Condition Creation functionCan't cast a stored procedure parameter?deteriorating stored procedure running timesSQL 2005 Unused proceduresDynamic SQL Server cross tabInvestigating errors from strange queryInsert results of spBlitzIndex stored procedure into tableINSERT/SELECT xml column from one table to another
Is honey really a supersaturated solution? Does heating to un-crystalize redissolve it or melt it?
How to terminate ping <dest> &
Brexit - No Deal Rejection
The German vowel “a” changes to the English “i”
Are all passive ability checks floors for active ability checks?
Why do passenger jet manufacturers design their planes with stall prevention systems?
What do you call the act of removing a part of a word and replacing it with an apostrophe
Is it possible to upcast ritual spells?
Have researchers managed to "reverse time"? If so, what does that mean for physics?
How to make healing in an exploration game interesting
Knife as defense against stray dogs
Describing a chess game in a novel
How to write cleanly even if my character uses expletive language?
Is a party consisting of only a bard, a cleric, and a warlock functional long-term?
Convergence in probability and convergence in distribution
Bacteria contamination inside a thermos bottle
Why one should not leave fingerprints on bulbs and plugs?
Problem with FindRoot
How do I change two letters closest to a string and one letter immediately after a string using Notepad++?
Adventure Game (text based) in C++
How difficult is it to simply disable/disengage the MCAS on Boeing 737 Max 8 & 9 Aircraft?
How could an airship be repaired midflight?
Why did it take so long to abandon sail after steamships were demonstrated?
Why does overlay work only on the first tcolorbox?
Giving EXEC (@Variable) a Column name and Concatenation
SQL SERVER 2008 TVF OR CHARINDEX to search column with commaOracle GoldenGate add trandata errorsDynamic Condition Creation functionCan't cast a stored procedure parameter?deteriorating stored procedure running timesSQL 2005 Unused proceduresDynamic SQL Server cross tabInvestigating errors from strange queryInsert results of spBlitzIndex stored procedure into tableINSERT/SELECT xml column from one table to another
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;
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
add a comment |
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;
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
add a comment |
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;
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
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;
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
sql-server
asked yesterday
Tom_WTom_W
423
423
add a comment |
add a comment |
4 Answers
4
active
oldest
votes
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.
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
yesterday
add a comment |
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
add a comment |
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
add a comment |
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
)
)
add a comment |
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
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
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
yesterday
add a comment |
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.
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
yesterday
add a comment |
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.
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.
edited yesterday
answered yesterday
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
yesterday
add a comment |
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
yesterday
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
yesterday
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
yesterday
add a comment |
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
add a comment |
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
add a comment |
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
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
answered yesterday
Dan GuzmanDan Guzman
14k21735
14k21735
add a comment |
add a comment |
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
add a comment |
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
add a comment |
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
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
answered yesterday
George.PalaciosGeorge.Palacios
2,328825
2,328825
add a comment |
add a comment |
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
)
)
add a comment |
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
)
)
add a comment |
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
)
)
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
)
)
answered yesterday
Jason WhitishJason Whitish
1456
1456
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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