Как я могу использовать параметр внутри sql openquery, например:
SELECT * FROM OPENQUERY([NameOfLinkedSERVER], 'SELECT * FROM TABLENAME
where field1=@someParameter') T1 INNER JOIN MYSQLSERVER.DATABASE.DBO.TABLENAME
T2 ON T1.PK = T2.PK
sql
parameters
openquery
разрыв69
источник
источник
Ответы:
В документации OPENQUERY говорится, что:
См. Эту статью для обходного пути.
ОБНОВИТЬ:
Как и было предложено, я включаю рекомендации из статьи ниже.
Передайте основные ценности
Если базовая инструкция Transact-SQL известна, но вам необходимо передать одно или несколько конкретных значений, используйте код, аналогичный приведенному в следующем примере:
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)
Передать весь запрос
Если вам нужно передать весь запрос Transact-SQL или имя связанного сервера (или и то, и другое), используйте код, похожий на следующий пример:
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 (@OPENQUERY+@TSQL)
Используйте хранимую процедуру Sp_executesql
Чтобы избежать многослойных кавычек, используйте код, похожий на следующий пример:
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
источник
INSERT INTO @TableVariable EXEC sp_executeSql @TSQL
SELECT * FROM tab WHERE col = 'Y'
. Для того, чтобы передать это заявление в виде строки в OpenQuery, все одиночные кавычки нужно спасся:SELECT * FROM OPENQUERY(Server, 'SELECT * FROM tab WHERE col = ''Y'' ')
. Затем, чтобы передать ВЫБРАТЬ с помощью OpenQuery для динамического SQL, эти кавычки должны быть экранированы:EXEC sp_executeSQL 'SELECT * FROM OPENQUERY(Server, ''SELECT * FROM tab WHERE col = ''''Y'''' '')'
. Надеюсь это поможет!SET @DAX = REPLACE(@DAX, '''', '''''')
Вы можете выполнить строку с OPENQUERY после ее создания. Если вы пойдете по этому пути, подумайте о безопасности и позаботьтесь о том, чтобы не объединять вводимый пользователем текст в ваш SQL!
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)
источник
if
, например, вif (SELECT Col1 FROM OPENQUERY('Select ...') > 0 ) BEGIN ... END
Со страницы MSDN :
По сути, это означает, что вы не можете выполнять динамический запрос. Чтобы добиться того, что пытается сделать ваш образец, попробуйте следующее:
SELECT * FROM OPENQUERY([NameOfLinkedSERVER], 'SELECT * FROM TABLENAME') T1 INNER JOIN MYSQLSERVER.DATABASE.DBO.TABLENAME T2 ON T1.PK = T2.PK where T1.field1 = @someParameter
Очевидно, что если ваша таблица TABLENAME содержит большой объем данных, они также будут передаваться по сети, и производительность может быть низкой. С другой стороны, для небольшого количества данных это хорошо работает и позволяет избежать накладных расходов на динамическое построение sql (внедрение sql, экранирование кавычек), которые
exec
могут потребоваться для данного подхода.источник
Собственно, мы нашли способ сделать это:
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
Это присвоит результат выполнения OpenQuery переменной @Output.
Мы тестировали процедуру Store в MSSQL 2012, но должны работать с MSSQL 2008+.
Microsoft утверждает, что sp_executesql (Transact-SQL): применимо к: SQL Server (от SQL Server 2008 до текущей версии), базе данных SQL Windows Azure (от первоначального выпуска до текущего выпуска). ( http://msdn.microsoft.com/en-us/library/ms188001.aspx )
источник
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 !$#@$@ thing in a string.
источник
SELECT field1 FROM OPENQUERY ([NameOfLinkedSERVER], 'SELECT field1 FROM TABLENAME') WHERE field1=@someParameter T1 INNER JOIN MYSQLSERVER.DATABASE.DBO.TABLENAME T2 ON T1.PK = T2.PK
источник
Объедините динамический SQL с OpenQuery. (Это идет на сервер Teradata)
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;
источник
В следующем примере я передаю параметр отдела в хранимую процедуру (spIncreaseTotalsRpt) и одновременно создаю временную таблицу из OPENQUERY. Таблица Temp должна быть глобальной Temp (##), чтобы на нее можно было ссылаться вне ее сущности. Используя exec sp_executesql, вы можете передать параметр отдела.
Примечание: будьте осторожны при использовании sp_executeSQL. Также ваш администратор может не иметь этой опции для вас.
Надеюсь, это кому-то поможет.
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
Полученные результаты
Увеличение долга Cnt 0 1 2 3 4 5 6 0,0000 1,0000 0,0000 0,0000 0,0000 0,0000 0,0000 0,0000
источник
Я нашел способ, который мне подходит. Это требует использования временной таблицы, к которой имеет доступ связанный сервер .
Я создал таблицу и заполнил ее нужными мне значениями, а затем ссылаюсь на эту таблицу через связанный сервер.
SELECT * FROM OPENQUERY(KHSSQLODSPRD,'SELECT * FROM ABC.dbo.CLAIM A WITH (NOLOCK) WHERE A.DOS >= (SELECT MAX(DATE) FROM KHSDASQL01.DA_MAIN.[dbo].[ALLFILENAMES]) ')
источник
declare @p_Id varchar(10) SET @p_Id = '40381' EXECUTE ('BEGIN update TableName set ColumnName1 = null, ColumnName2 = null, ColumnName3 = null, ColumnName4 = null where PERSONID = '+ @p_Id +'; END;') AT [linked_Server_Name]
источник
openquery
должен знать и этот подход. Кроме того, он намного чище. Итак, +1 с моей стороны.Мы можем использовать
execute
метод вместоopenquery
. Его код намного чище. Мне нужно было получитьlinked server
результат запроса в переменной. Я использовал следующий код.CREATE TABLE #selected_store ( code VARCHAR(250), id INT ) declare @storeId as integer = 25 insert into #selected_store (id, code) execute('SELECT store_id, code from quickstartproductionnew.store where store_id = ?', @storeId) at [MYSQL] declare @code as varchar(100) select @code = code from #selected_store select @code drop table #selected_store
Заметка:
источник
Простой пример, основанный на приведенном выше примере @Tuan Zaidi, который казался самым простым. Не знал, что вы можете сделать фильтр вне OPENQUERY ... намного проще!
Однако в моем случае мне нужно было поместить его в переменную, поэтому я создал дополнительный уровень подзапроса, чтобы вернуть одно значение.
SET @SFID = (SELECT T.Id FROM (SELECT Id, Contact_ID_SQL__c FROM OPENQUERY([TR-SF-PROD], 'SELECT Id, Contact_ID_SQL__c FROM Contact') WHERE Contact_ID_SQL__c = @ContactID) T)
источник