2017-05-26 1 views
0

J'essaie de m'enseigner à la fois les curseurs SQL et sp_executesql pour un projet sur lequel je travaille. Je suis assez proche, je pense, mais je n'arrive pas à obtenir ce que je veux, et j'espère que quelqu'un pourra m'aider à surmonter mon manque de connaissances. Merci d'avance pour toute aide!Difficulté à apprendre sp_executesql dans SQL Server

Ce qui suit est mon code actuel (les annotations commentées me parlent à moi-même):

DECLARE @form_id INT 
DECLARE @element_table NVARCHAR(50) 
DECLARE @element_column NVARCHAR(50) 
DECLARE @element_id INT 
DECLARE @sqlString NVARCHAR(1000) 
DECLARE @sqlDefinition NVARCHAR(1000) 
DECLARE @outputDataType VARCHAR(50) 
DECLARE @parmRET1 VARCHAR(30) 
DECLARE @sqlresult VARCHAR(50) 
DECLARE @passed_element_table NVARCHAR(50) 
DECLARE @passed_element_column NVARCHAR(50) 

SET @form_id = 220 --- temporary value for testing 

--- this gets the list of ELEMENT_IDs for the cursor 
DECLARE db_cursor CURSOR FOR SELECT 
    ELEMENT_ID 
FROM FORM_ELEMENT fe 
WHERE fe.FORM_ID = @form_id 

--- Cursor loop starts here 
OPEN db_cursor 

FETCH NEXT FROM db_cursor INTO @element_id 

WHILE @@fetch_status = 0 
BEGIN 

--- These two SET statements get me the table name and column I want to retrieve the datatype for 
SET @element_table = (
    SELECT DISTINCT 
     mtm.MAP_TABLE_NAME 
    FROM FORM_ELEMENT fe 
    LEFT OUTER JOIN ELEMENT e 
     ON fe.ELEMENT_ID = e.ELEMENT_ID 
    LEFT OUTER JOIN FORM_DATA_MAPPING_MASTER fdmm 
     ON fe.FORM_DATA_MAPPING_ID = fdmm.FORM_DATA_MAPPING_ID 
    LEFT OUTER JOIN MAPPING_TABLE_MASTER mtm 
     ON fdmm.MAP_TABLE_ID = mtm.MAP_TABLE_ID 
    INNER JOIN FORM f 
     ON fe.FORM_ID = f.FORM_ID 
    WHERE fe.FORM_ID = @form_id 
    AND fe.ELEMENT_ID = @element_id 
) 
SET @element_column = (
    SELECT DISTINCT 
     mcm.MAP_COLUMN_NAME 
    FROM FORM_ELEMENT fe 
    LEFT OUTER JOIN ELEMENT e 
     ON fe.ELEMENT_ID = e.ELEMENT_ID 
    LEFT OUTER JOIN FORM_DATA_MAPPING_MASTER fdmm 
     ON fe.FORM_DATA_MAPPING_ID = fdmm.FORM_DATA_MAPPING_ID 
    LEFT OUTER JOIN MAPPING_COLUMN_MASTER mcm 
     ON fdmm.MAP_COLUMN_ID = mcm.MAP_COLUMN_ID 
    WHERE fe.FORM_ID = @form_id 
    AND fe.ELEMENT_ID = @element_id 
) 

--- This is where I begin building the dynamic sql. I'm unsure if I need the DECLARE statement here, if I've used it above 
SET @sqlString = N'DECLARE @sqlResult VARCHAR(50) SET @sqlResult = (SELECT DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @passed_element_table AND COLUMN_NAME = @passed_element_column)' 
SET @sqlDefinition = N'@passed_element_table nvarchar(50), @passed_element_column nvarchar(50), @outputDataType varchar(30) OUTPUT' 
SET @passed_element_table = @element_table 
SET @passed_element_column = @element_column 

--- This is where I execute the dynamic sql 
EXECUTE sp_executesql @sqlString 
       , @sqlDefinition 
       , @passed_element_table = @element_table 
       , @passed_element_column = @element_column 
       , @outputDataType = @sqlresult OUTPUT 

--- Here I'm just using a print statement to dump out the results of the prior SP execution 
PRINT @element_table + ' | ' + @element_column + ' | ' + 
CASE 
    WHEN @outputDataType IS NULL THEN '' 
    ELSE @outputDataType 
END 

--- This ends the loop for this element_id, and restarts the process 
FETCH NEXT FROM db_cursor INTO @element_id 

END 

--- This finishes the cursor loop, and then deallocates the cursor when there are no more element_ids 
CLOSE db_cursor 
DEALLOCATE db_cursor 

La requête est exécutée sans erreur (une victoire), mais il ne semble pas obtenir des valeurs de retour à partir du sous-programme sp_executesql. Voici un exemple de la sortie de retour:

BIOGRAPH_MASTER | BIRTH_DTE | 
BIOGRAPH_MASTER | SSN | 
BIOGRAPH_ETHNIC_RACE | RACE | 
BIOGRAPH_ETHNIC_RACE | ETHNICITY | 
NAME_MASTER | UDEF_1A_2 | 
ADDRESS_MASTER | ADDR_LINE_1 | 
ADDRESS_MASTER | ADDR_LINE_2 | 
ADDRESS_MASTER | CITY | 
ADDRESS_MASTER | STATE | 

Je suis assez sûr que j'ai une erreur dans la façon dont je l'ai construit le @sqlstring à envoyer au sp_executesql, mais je ne peux pas trouver une bonne ressource pour aider Je comprends où je me suis trompé. Comme je l'ai déjà dit, toute aide serait grandement appréciée.

+1

Puisque vous luttez avec les curseurs, vous devez désapprendre ce que vous avez appris et éloigne-toi d'eux. Les curseurs sont horribles du point de vue de la performance. Il y a presque toujours un moyen basé sur l'ensemble pour accomplir la plupart des choses. Si vous pouvez expliquer ce que vous essayez de faire ici, je serais heureux de vous aider à trouver une solution sans utiliser de curseurs. –

Répondre

0
PRINT @element_table + ' | ' + @element_column + ' | ' + 
CASE 
    WHEN @SqlResult IS NULL THEN '' 
    ELSE @SqlResult 
END 

Vous où regarder la variable intérieure.

aussi:

SET @sqlString = N'DECLARE @sqlResult VARCHAR(50) SELECT @outputDataType = DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @passed_element_table AND COLUMN_NAME = @passed_element_column' 

serait plus clair

encore plus évident:

SELECT @outputDataType = DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @passed_element_table AND COLUMN_NAME = @passed_element_column 

sans sp_executesql

0

Je suis sûr qu'il aurait besoin de lire comme ceci

EXECUTE sp_executesql @sqlString 
      , @sqlDefinition 
      , @element_table 
      , @element_column 
      , @sqlresult OUTPUT 

puis dans votre impression référence ceux-ci. vous aurez également besoin d'ajouter ces DECLARE déclare @passed_element_table NVARCHAR (50) DECLARE @passed_element_column NVARCHAR (50)

au @sqlString