SELECT balance FROM LINKED_DB..TEST.ACCOUNT WHERE id = 12345
or, with the parameter method:
declare @id int
set @id = 12345
SELECT balance FROM LINKED_DB..TEST.ACCOUNT WHERE id = @id
Syntax note:
LINKED_DB..TEST.ACCOUNT is the so-called four-parts name, build as:
<linked_server_name>.<dataSELECT balance FROM LINKED_DB...TEST_ACCOUNT
A first issue with this could be that, for whatever reason, the filtering is not occurring on the remote db, but locally; which means that the full table data is fetched locally before filtering. Imagine you happen to get that on a big table!
SELECT * FROM OPENQUERY(LINKED_DB, 'SELECT balance FROM TEST.ACCOUNT WHERE id = 12345')
While this should work, and most will know, if the id value is a parameter, you would need to build the sql like this:
Declare @id int -- would be the parameter for the stored procedure, for example
set @id = 12345
Declare @sql varchar(max)
Set @sql = 'SELECT * FROM OPENQUERY(LINKED_DB, ''SELECT balance FROM TEST.ACCOUNT WHERE id = ' + cast(@id as varchar(100)) + ' '') '
exec(@sql)
That will execute fine, but you can surely see how dull this kind of code will look like, especially if the parameter is text and not a number (more quotes to be added …). Another danger here is that if the coder forgets to care about
SQL Injection, the whole instance (and via the linked servers, even those remote databases) is at risk!
Declare @id int -- would be the parameter for the stored procedure, for example
set @id = 12345
Declare @balance int --- output value
Declare @sql nvarchar(max)
Set @sql = 'SELECT @res = balance FROM OPENQUERY(LINKED_DB, ''SELECT balance FROM TEST.ACCOUNT WHERE id = ' + cast(@id as varchar(100)) + ' '') '
exec sp_executesql @sql, N'@res int OUTPUT', @balance OUTPUT
This also works to get several columns from the table, but still, the usuage of input parameter @id is not really "nice".
Declare @id int --- would be the parameter for the stored procedure, for example
set @id = 12345
Declare @balance int --- output value
Declare @sql nvarchar(max)
Set @sql = 'BEGIN SELECT balance INTO ? FROM TEST.ACCOUNT WHERE id = ?; END; '
EXECUTE(@sql, @balance OUTPUT, @id) AT [LINKED_DB]
Much easier to read, and no quoting problems, no data type issues.
Of course, you can run plain sql to fetch multiple records, with parameters:EXECUTE ('SELECT * FROM TEST.ACCOUNT WHERE id >= ? AND ROWNUM <= ? ', 12345, 10) AT [LINKED_DB]
Or insert the results into a local (fixed, temp or variable) table:CREATE TABLE #tmp ( id INT , balance INT )
INSERT INTO #tmp
EXECUTE ('SELECT id, balance FROM TEST.ACCOUNT WHERE id >= ? AND ROWNUM <= ? ', 12345, 10) AT [LINKED_DB]
Select * from #tmp
Drop table #tmp
EXECUTE ('INSERT INTO TEST.ACCOUNT (id, balance) VALUES (?,?)', 54321, 0) AT [LINKED_DB]
EXECUTE ('UPDATE TEST.ACCOUNT SET balance = balance + ? WHERE id = ?', 10, 54321) AT [LINKED_DB]
All you need to take care of is the order of the parameters!
Msg 7411, Level 16, State 1, Line 1
Server 'LINKED_DB' is not configured for RPC.
This error just tells you that you have to configure the
RPC and RPC OUT in the linked server’s properties.
OLE DB provider "OraOLEDB.Oracle" for linked server "LINKED_DB" returned message "New transaction cannot enlist in the specified transaction coordinator. ".
Msg 7391, Level 16, State 2, Line 16
The operation could not be performed because OLE DB provider "OraOLEDB.Oracle" for linked server "LINKED_DB" was unable to begin a distributed transaction.
This can be solved using the registry tweak described in general in this article:
http://support.microsoft.cHave a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.
Comments (1)
Author
Commented:http://technet.microsoft.com/en-us/library/ms188332.aspx