2016-07-19 3 views
0

Lorsque j'exécute cette requête (c'est une fonction scalaire), j'obtiens le résultat souhaité. Il renvoie un numéro d'expédition.Comment échanger un paramètre pour une valeur VARCHAR spécifique utilisée pour un serveur lié avec openquery

select ShipmentNo from openquery([SERVER_IP], 'SET FMTONLY OFF EXEC GsvStaging.dbo.Paul_GetPoShippingLabels @CartId = NULL, @CpPoNo = ''G015246''') 

Cependant, quand je swap sur G015246 avec le paramètre @PO:

select @ShipmentLabels = ShipmentNo from openquery([SERVER_IP], 'SET FMTONLY OFF EXEC GsvStaging.dbo.Paul_GetPoShippingLabels @CartId = NULL, @CpPoNo = ''@PO''') 

Pour une raison quelconque la valeur de retour devient nulle avec ce changement.

Ma déclaration de retour pour les deux est:

RETURN ISNULL(@ShipmentLabels, @PO) 

@ShipmentLabels est la valeur de retour souhaitée. Comme il est nul, il renvoie @PO à la place, ce qui finit par être G015246 ce qui semble juste.

Quelqu'un remarque-t-il quelque chose de mal dans la façon dont j'ai ajouté le paramètre @PO à l'instruction sql?

procédure stockée qui appelle la fonction (fnGetTheShippingLabels): Je suppose que la meilleure façon de décrire ce SP est le point de départ. Comme vous pouvez le voir ci-dessus, la fonction se trouve dans l'instruction SELECT du fournisseur de services (SP).

Scalar complète Fonction:

ALTER FUNCTION [dbo].[fnGetTheShippingLabels] 
(
    @PoHdrRecId INT, 
    @PoNo VARCHAR(20) 
) 
RETURNS VARCHAR(220) 
AS 
BEGIN 
DECLARE @PO VARCHAR(20)= @PoNo 
DECLARE @ShipmentLabels VARCHAR(220) 

    select @ShipmentLabels = ShipmentNo from openquery([SERVER_IP], 'SET FMTONLY OFF EXEC GsvStaging.dbo.Paul_GetPoShippingLabels @CartId = NULL, @CpPoNo = ''G015246''') 
--FROM dbo.PoHdr WHERE PoNo = @PoNo 

    -- Return the result of the functionRETURN ISNULL(@ShipmentLabels, @PO) 

END 

Essayer une autre façon de requête d'écriture maintenant, cela ne fonctionne pas FYI:

Declare @TSQL VarChar(8000) 

    set @TSQL = N'select @ShipmentLabels = ShipmentNo from openquery([SERVER_IP],SET FMTONLY OFF EXEC GsvStaging.dbo.Paul_GetPoShippingLabels @CartId = NULL, @CpPoNo =' + @PO +'' 
    exec sp_executesql @TSQL, N'@ShipmentLabels output', @ShipmentLabels = @ShipmentLabels out 
+0

Je n'ai jamais essayé cela - mais avez-vous essayé sans les guillemets? '@CpPoNo = '@ PO''' SQL Server lit votre paramètre comme un littéral de chaîne (VARCHAR) de la façon dont vous l'avez, je suis assez sûr. – scsimon

+0

Je ne le fais peut-être pas correctement, mais '@CpPoNo = '@ PO''' et' @CpPoNo = @ PO'' ne s'exécuteront pas. Ce dernier donne une erreur renvoyée message ... "Préparation différée n'a pas pu être complétée.". Msg 8180, niveau 16, état 1, ligne 1 Énoncé (s) n'a pas pu être préparé. Msg 137, niveau 15, état 2, ligne 1 Doit déclarer la variable scalaire "@PO". – user1869407

+0

Je viens de remarquer que c'est dans votre SP. vous avez juste besoin de concaténer avec +. '@CpPoNo = '+ @ PO' – scsimon

Répondre

0

Je vois que cela peut se faire de deux façons

Option 1 Création d'une requête dynamique et Passage le paramètre de sortie

Declare @TSQL VarChar(8000) 
DECLARE @SQ VARCHAR(4) = '''' 
DECLARE @paramDef VARCHAR(100) 

set @TSQL = N'select @ShipmentLabels = ShipmentNo from openquery([SERVER_IP],SET FMTONLY OFF EXEC GsvStaging.dbo.Paul_GetPoShippingLabels @CartId = NULL, @CpPoNo =' + @SQ + @PO + @SQ + ')' 
SET @paramDef = N'@ShipmentLabels VARCHAR(1000) OUTPUT' 
exec sp_executesql @TSQL, @paramDef, @ShipmentLabels = @ShipmentLabels OUTPUT 

Option 2 Création d'une requête dynamique, obtenir la valeur dans une table temporaire et la lecture de la valeur de la table temporaire.

Declare @TSQL VarChar(8000) 
DECLARE @SQ VARCHAR(4) = '''' 
DECLARE @ShipmentNo VARCHAR(1000) 
set @TSQL = N'select ShipmentNo from openquery([SERVER_IP],SET FMTONLY OFF EXEC GsvStaging.dbo.Paul_GetPoShippingLabels @CartId = NULL, @CpPoNo =' + @SQ + @PO + @SQ + ')' 

CREATE TABLE #T 
(
    temp VARCHAR(max) 
) 
INSERT INTO #T 
EXEC(@TSQL) 

SELECT @ShipmentNo = temp from #t 
SELECT @ShipmentNo 
drop table #t 

La solution complète avec votre procédure stockée ressemblera, je l'ai écrit avec un curseur et tout, il peut encore améliorer la performance, mais avec notre limité sur la conception de votre DB c'est la meilleure solution, nous pouvons vous pourvoir

ALTER PROCEDURE [dbo].[StartingSP] 
    @JobId INT = 1 

AS 
BEGIN 
    SET NOCOUNT ON; 
    DECLARE @ErrorMsg VARCHAR(256) 
    DECLARE @PoNO VARCHAR(1000) 

    Declare @TSQL VarChar(8000) 
    DECLARE @SQ VARCHAR(4) = '''' 
    DECLARE @ShipmentNo VARCHAR(1000) 
    set @TSQL = N'select ShipmentNo,' + @SQ + @PO + @SQ +' as PoNo from openquery([SERVER_IP],SET FMTONLY OFF EXEC GsvStaging.dbo.Paul_GetPoShippingLabels @CartId = NULL, @CpPoNo =' + @SQ + @PO + @SQ + ')' 

    CREATE TABLE #T1 
    (
     temp VARCHAR(max) 
    ) 
    INSERT INTO #T1 
    EXEC(@TSQL) 

    SELECT OC.PoNo, 
      V.FirstName, 
      V.LastName, 
      dbo.fnGetTradeAppFacilityName(NULL,OC.PoNo) TradeAppFacilityName, 
      OC.ReportFileName 
      ,'' as 
      --, dbo.fnGetTheShippingLabels(NULL,OC.PoNo) ShippingLabels 
    INTO #T 
    FROM  PoHdr P 
     INNER JOIN OrderConfirmation OC ON 
      OC.PoNo = P.PoNo 
     INNER JOIN CpVendor V ON 
      V.VendNo = P.VendNo 
    WHERE OC.JobId = @JobId 



    Declare @TSQL VarChar(8000) 
    DECLARE @SQ VARCHAR(4) = '''' 
    DECLARE @ShipmentNo VARCHAR(1000) 
    CREATE TABLE #T1 
    (
     PoNo VARCHAR(1000),ShipmentNo VARCHAR(max) 
    ) 

    DECLARE vend_cursor CURSOR 
     FOR SELECT PoNO FROM #T 
    OPEN vend_cursor 

    FETCH NEXT FROM vendor_cursor 
    INTO @PoNO 

    WHILE @@FETCH_STATUS = 0 
    BEGIN 

     set @TSQL = N'select ShipmentNo,' + @SQ + @PO + @SQ +' as PoNo from openquery([SERVER_IP],SET FMTONLY OFF EXEC GsvStaging.dbo.Paul_GetPoShippingLabels @CartId = NULL, @CpPoNo =' + @SQ + @PO + @SQ + ')' 

     INSERT INTO #T1 
     EXEC(@TSQL)  

     FETCH NEXT FROM vendor_cursor 
     INTO @PoNO 
    END 
    CLOSE vendor_cursor 
    DEALLOCATE vendor_cursor 

    UPDATE T 
    SET T.ShippingLabels = T1.ShipmentNo 
    FROM #T T 
    JOIN #T1 T1 
    ON T.PoNo = T1.PoNo 

    SELECT @ErrorMsg ErrorMsg 

END 
+0

Je reçois l'erreur suivante: Seules les fonctions et certaines procédures stockées étendues peuvent être exécutées depuis une fonction. System.Data.SqlClient.SqlException (0x80131904): Seules les fonctions et certaines procédures stockées étendues peuvent être exécutées à partir d'une fonction. Utilisation de SQL dynamique – user1869407

+0

Reportez-vous au code "mise à jour" ci-dessus – user1869407

+0

Aucune des options ne fonctionne. L'erreur pour l'option 2 est "Utilisation invalide d'un opérateur à effet latéral" SELECT "dans une fonction" – user1869407