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.
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. –