web-dev-qa-db-de.com

einschließlich der Parameter in OPENQUERY

Wie kann ich einen Parameter in SQL-Openquery verwenden, z. 

SELECT * FROM OPENQUERY([NameOfLinkedSERVER], 'SELECT * FROM TABLENAME
where [email protected]') T1 INNER JOIN MYSQLSERVER.DATABASE.DBO.TABLENAME
T2 ON T1.PK = T2.PK
69
gaponte69

Aus der OPENQUERY -Dokumentation heißt es:

OPENQUERY akzeptiert keine Variablen für seine Argumente.

In diesem Artikel finden Sie eine Problemumgehung.

UPDATE:

Wie vorgeschlagen, füge ich die Empfehlungen aus dem folgenden Artikel hinzu.

Grundwerte übergeben

Wenn die grundlegende Transact-SQL-Anweisung bekannt ist, Sie jedoch einen oder mehrere bestimmte Werte übergeben müssen, verwenden Sie Code, der dem folgenden Beispiel ähnelt: 

DECLARE @TSQL varchar(8000), @VAR char(2)
SELECT  @VAR = 'CA'
SELECT  @TSQL = 'SELECT * FROM OPENQUERY(MyLinkedServer,''SELECT * FROM pubs.dbo.authors WHERE state = ''''' + @VAR + ''''''')'
EXEC (@TSQL)

Pass die ganze Abfrage

Wenn Sie die gesamte Transact-SQL-Abfrage oder den Namen des Verbindungsservers (oder beide) übergeben müssen, verwenden Sie Code, der dem folgenden Beispiel ähnelt:

DECLARE @OPENQUERY nvarchar(4000), @TSQL nvarchar(4000), @LinkedServer nvarchar(4000)
SET @LinkedServer = 'MyLinkedServer'
SET @OPENQUERY = 'SELECT * FROM OPENQUERY('+ @LinkedServer + ','''
SET @TSQL = 'SELECT au_lname, au_id FROM pubs..authors'')' 
EXEC (@[email protected]) 

Verwenden Sie die gespeicherte Prozedur Sp_executesql

Verwenden Sie Code, der dem folgenden Beispiel ähnelt, um die mehrschichtigen Anführungszeichen zu vermeiden:

DECLARE @VAR char(2)
SELECT  @VAR = 'CA'
EXEC MyLinkedServer.master.dbo.sp_executesql
N'SELECT * FROM pubs.dbo.authors WHERE state = @state',
N'@state char(2)',
@VAR
121
Garett

Sie können einen String mit OPENQUERY ausführen, sobald Sie ihn aufgebaut haben. Wenn Sie diese Route wählen, sollten Sie über die Sicherheit nachdenken und darauf achten, dass der vom Benutzer eingegebene Text nicht in SQL gespeichert wird.

DECLARE @Sql VARCHAR(8000)
SET @Sql = 'SELECT * FROM Tbl WHERE Field1 < ''someVal'' AND Field2 IN '+ @valueList 
SET @Sql = 'SELECT * FROM OPENQUERY(SVRNAME, ''' + REPLACE(@Sql, '''', '''''') + ''')'
EXEC(@Sql)
14
Tahbaza

Auf der MSDN-Seite :

OPENQUERY akzeptiert keine Variablen für seine Argumente

Grundsätzlich bedeutet dies, dass Sie keine dynamische Abfrage ausgeben können. Versuchen Sie Folgendes, um zu erreichen, was Ihre Probe versucht:

SELECT * FROM 
   OPENQUERY([NameOfLinkedSERVER], 'SELECT * FROM TABLENAME') T1 
   INNER JOIN 
   MYSQLSERVER.DATABASE.DBO.TABLENAME T2 ON T1.PK = T2.PK 
where
   T1.field1 = @someParameter

Wenn Ihre TABLENAME-Tabelle eine große Datenmenge enthält, wird dies natürlich auch über das Netzwerk übertragen und die Leistung ist möglicherweise schlecht. Auf der anderen Seite funktioniert dies bei einer kleinen Datenmenge gut und vermeidet den dynamischen Aufwand für SQL-Konstruktionen (SQL-Injection, Escape-Anführungszeichen), den ein exec-Ansatz erfordert.

11
Neil Moss

Eigentlich haben wir einen Weg gefunden, dies zu tun:

DECLARE @username varchar(50)
SET @username = 'username'
DECLARE @Output as numeric(18,4)
DECLARE @OpenSelect As nvarchar(500)
SET @OpenSelect = '(SELECT @Output = CAST((CAST(pwdLastSet As bigint) / 864000000000) As numeric(18,4)) FROM OpenQuery (ADSI,''SELECT pwdLastSet
                                FROM  ''''LDAP://domain.net.intra/DC=domain,DC=net,DC=intra''''
                                WHERE objectClass =  ''''User'''' AND sAMAccountName = ''''' + @username + '''''
                          '') AS tblADSI)'
EXEC sp_executesql @OpenSelect, N'@Output numeric(18,4) out', @Output out
SELECT @Output As Outputs

Dadurch wird das Ergebnis der OpenQuery-Ausführung in der Variablen @Output zugewiesen.

Wir haben das Store-Verfahren in MSSQL 2012 getestet, sollten jedoch mit MSSQL 2008+ zusammenarbeiten.

Microsoft sagt, dass sp_executesql (Transact-SQL) gilt: Betrifft: SQL Server (SQL Server 2008 bis zur aktuellen Version), Windows Azure SQL-Datenbank (Anfangsversion bis zur aktuellen Version). ( http://msdn.Microsoft.com/de-de/library/ms188001.aspx )

6
Juan Medina
DECLARE @guid varchar(36);  select @guid= convert(varchar(36), NEWID() );
/*
    The one caveat to this technique is that ##ContextSpecificGlobal__Temp should ALWAYS have the exact same columns.  
    So make up your global temp table name in the sproc you're using it in and only there!
    In this example I wanted to pass in the name of a global temporary table dynamically.  I have 1 procedure dropping 
    off temporary data in whatever @TableSrc is and another procedure picking it up but we are dynamically passing 
    in the name of our pickup table as a parameter for OPENQUERY.
*/
IF ( OBJECT_ID('tempdb..##ContextSpecificGlobal__Temp' , 'U') IS NULL )
    EXEC ('SELECT * INTO ##ContextSpecificGlobal__Temp FROM OPENQUERY(loopback, ''Select *,''''' +  @guid +''''' as tempid FROM ' + @TableSrc + ''')')
ELSE 
    EXEC ('INSERT ##ContextSpecificGlobal__Temp SELECT * FROM OPENQUERY(loopback, ''Select *,''''' +  @guid +''''' as tempid FROM ' + @TableSrc + ''')')

--If this proc is run frequently we could run into race conditions, that's why we are adding a guid and only deleting
--the data we added to ##ContextSpecificGlobal__Temp
SELECT * INTO #TableSrc FROM ##ContextSpecificGlobal__Temp WHERE tempid = @guid

BEGIN TRAN t1
    IF ( OBJECT_ID('tempdb..##ContextSpecificGlobal__Temp' , 'U') IS NOT NULL ) 
    BEGIN
        -- Here we wipe out our left overs if there if everyones done eating the data
        IF (SELECT COUNT(*) FROM ##ContextSpecificGlobal__Temp) = 0
            DROP TABLE ##ContextSpecificGlobal__Temp
    END
COMMIT TRAN t1

-- YEAH! Now I can use the data from my openquery without wrapping the whole !$#@[email protected] thing in a string.
4
Ryan Maloney
SELECT field1 FROM OPENQUERY 
                   ([NameOfLinkedSERVER], 
                   'SELECT field1 FROM TABLENAME') 
                           WHERE [email protected] T1 
                                 INNER JOIN MYSQLSERVER.DATABASE.DBO.TABLENAME           
                                 T2 ON T1.PK = T2.PK
2
Tuan Zaidi

Im folgenden Beispiel übergebe ich einen Abteilungsparameter an eine gespeicherte Prozedur (spIncreaseTotalsRpt) und zur gleichen Zeit erstelle ich eine temporäre Tabelle aus einer OPENQUERY . Die temporäre Tabelle muss eine globale Temp (## ) so kann es außerhalb seiner Intance referenziert werden. Mit exec sp_executesql können Sie den Abteilungsparameter übergeben.

Hinweis: Seien Sie vorsichtig, wenn Sie sp_executeSQL verwenden. Möglicherweise steht Ihrem Administrator diese Option möglicherweise nicht zur Verfügung.

Hoffe das hilft jemandem. 

 IF OBJECT_ID('tempdb..##Temp') IS NOT NULL
/*Then it exists*/
    begin
       DROP TABLE ##Temp
    end 
 Declare @Dept as nvarchar(20) ='''47'''

 declare @OPENQUERY  as nvarchar(max)
set @OPENQUERY = 'Select ' + @Dept + ' AS Dept,  * into ##Temp from openquery(SQL_AWSPROD01,''' 

declare @sql nvarchar(max)= @openquery +  'SET FMTONLY OFF EXECUTE SalaryCompensation.dbo.spIncreaseTotalsRpts ' + '''' + @Dept + ''''  + ''')'
declare @parmdef nvarchar(25) 
DECLARE @param nvarchar(20) 

SET @parmdef = N'@Dept varchar(20)'
-- select @sql
-- Print @sql + @parmdef  + @dept
exec sp_executesql @sql,@parmdef, @Dept  
Select * from ##Temp

Ergebnisse 

Dept-Erhöhung Cnt 0 1 2 3 4 5 6 0,0000 1,0000 0,0000 0,0000 0,0000 0,0000 0,0000 0,0000

1
Carlos

Kombinieren Sie Dynamic SQL mit OpenQuery. (Dies geht zu einem Teradata-Server)

DECLARE 
    @dayOfWk    TINYINT = DATEPART(DW, GETDATE()),
    @qSQL       NVARCHAR(MAX) = '';

SET @qSQL = '
SELECT
    *
FROM
    OPENQUERY(TERASERVER,''
        SELECT DISTINCT
            CASE
                WHEN ' + CAST(@dayOfWk AS NCHAR(1)) + ' = 2
                THEN ''''Monday''''
                ELSE ''''Not Monday''''
            END
        '');';

EXEC sp_executesql @qSQL;
0
Mike

Ich habe einen Weg gefunden, der für mich funktioniert. Es ist jedoch die Verwendung einer Scratch-Tabelle erforderlich, auf die ein Linked Server Zugriff hat.

Ich habe eine Tabelle erstellt und mit den Werten gefüllt, die ich brauche. Dann referenziere ich diese Tabelle über einen Verbindungsserver.

SELECT * 
FROM OPENQUERY(KHSSQLODSPRD,'SELECT *
  FROM ABC.dbo.CLAIM A WITH (NOLOCK)
  WHERE A.DOS >= (SELECT MAX(DATE) FROM KHSDASQL01.DA_MAIN.[dbo].[ALLFILENAMES]) ')
0
Hannover Fist