2010-06-03 35 views
2

J'ai un certain nombre de procédures stockées de structure similaire à ceci:Comment gérer un ensemble de résultats vide d'un appel OpenQuery au serveur d'analyse lié en SQL dynamique?

DECLARE @sql NVARCHAR(MAX) 
DECLARE @mdx NVARCHAR(MAX) 

CREATE table #result 
(
    [col1] NVARCHAR(50), 
    [col2] INT, 
    [col3] INT 
) 

SET @mdx = '{some dynamic MDX}' 
SET @sql = 'SELECT a.* FROM OpenQuery(LinkedAnalysisServer, ''' + @mdx + ''') AS a' 

INSERT INTO #result 
EXEC sp_executesql @sql 
SELECT * FROM #result 

Cela fonctionne très bien lorsque les résultats existent dans le cube. Cependant, lorsque les résultats de Openquery sont vides, l'INSERT échoue avec cette erreur:

Column name or number of supplied values does not match table definition.

Ma question est, quelle est la meilleure façon de gérer ce scénario? J'utilise les résultats dans un fichier de rapport statique (.rdlc), donc le typage explicite de la table temporaire est (j'en suis sûr) requis.

Répondre

4

Utilisez TRY/CATCH dans votre procédure stockée, vous remarquerez qu'il existe un numéro d'erreur spécifique pour votre problème, vérifiez le numéro d'erreur et si c'est le cas, renvoyez un jeu de résultats vide. Comme vous avez déjà défini la table, cela sera plus facile.

pseudocode ressemble à ceci:

SET @mdx = '{some dynamic MDX}' 
SET @sql = 'SELECT a.* FROM OpenQuery(LinkedAnalysisServer, ''' + @mdx + ''') AS a' 

BEGIN TRY 

INSERT INTO #result 
EXEC sp_executesql @sql 

END TRY 
BEGIN CATCH 

    IF ERROR_NUMBER <> 'The error number you are seeing' 
    BEGIN 
    RAISERROR('Something happened that was not an empty result set') 
    END 

END CATCH 

SELECT * FROM #result 

Vous voulez vérifier cette erreur particulière, de sorte que vous ne le juste retour des jeux de résultats vide si votre serveur tombe en panne SSAS par exemple.

+1

Juste pour être complet, je note que les parenthèses sont nécessaires sur ERROR_NUMBER(), et que le nombre retourné dans ce cas est 213. Ma solution temporaire était de supprimer le NON EMPTY() sur mes axes ROWS et COLUMNS dans la requête MDX dynamique, mais ce n'était pas idéal car les tables vides/sparse qu'il retournait étaient moche. Cela fonctionne beaucoup plus bien, merci. –

+0

Ah oui, merci pour clarifier - j'écrivais ça à la maison de la mémoire :) – Meff

+0

@MrPalomar, aussi j'ai utilisé la technique "Catch/ReThrow" expliquée ici: http://stackoverflow.com/questions/1673892/is-there -an-equivalent-in-t-sql-to-cs-throw-to-re-throw-exceptions afin de "Bubble Up" l'exception aux couches supérieures, de sorte que vous pouvez dire si le serveur SSAS a planté, ou si vous avez le mot de passe Wring, ou si la requête a une erreur, et ainsi de suite. – Meff

0

Il existe une autre solution à ce problème, similaire à la réponse acceptée, qui consiste à utiliser une instruction IF au lieu de TRY ... CATCH.

http://www.triballabs.net/2011/11/overcoming-openquery-mdx-challenges/

IF (SELECT COUNT(*) 
    FROM OPENQUERY("SSAS1", 
     'SELECT [Measures].[Target Places] ON COLUMNS 
     FROM [ebs4BI_FactEnrolment] 
     WHERE [DimFundingYear].[Funding Year].&amp;[17]')) > 0 
    EXEC sp_executesql N'SELECT CONVERT(varchar(20), 
    "[DimPAPSCourse].[Prog Area].[Prog Area].[MEMBER_CAPTION]") 
    as ProgArea, 
    convert(float, "[Measures].[Target Places]") as Target 
    FROM OPENQUERY("SSAS1", 
    ''SELECT [Measures].[Target Places] ON COLUMNS, 
    [DimPAPSCourse].[Prog Area].[Prog Area] ON ROWS 
    FROM [ebs4BI_FactEnrolment] 
    WHERE [DimFundingYear].[Funding Year].&[17]'')' 
ELSE 
    SELECT '' as ProgArea, 0 as Target 
    WHERE 1=0