Mục lục
- Tổng quan
- Mệnh đề WHERE
- Tham gia nhiều bảng
- Bảng cục bộ được đính kèm với một bảng từ xa
- Chèn, Cập nhật và Xóa
- Cập nhật
- Cập nhật với các tham số
- Chèn Bản ghi Mới và Gặp lỗi BLOB
- Lấy Id Salesforce cho Bản ghi Cuối cùng Bạn đã Chèn
- Cập nhật dữ liệu SQL Server khi dữ liệu của Salesforce thay đổi
- Xác thực giản đồ lười biếng
- Hạn chế của OLEDB của Microsoft dành cho Nhà cung cấp ODBC
- Làm cách nào để tìm các bản ghi có nguồn cấp dữ liệu dòng (dòng mới) trong địa chỉ thanh toán?
- Tôi có thể xem bảng nào có sẵn thông qua phần mềm Easysoft không?
- Tôi có thể xem những cột nào có sẵn thông qua phần mềm Easysoft không?
- Tôi có thể tạo một máy chủ được liên kết theo chương trình không?
Tổng quan
Tài liệu này đưa ra một số mẹo sử dụng SQL Server với Salesforce. Các thành phần được sử dụng để kết nối SQL Server với Salesforce là Máy chủ liên kết SQL Server và Trình điều khiển ODBC Easysoft Salesforce. Cách bạn kết nối SQL Server với Salesforce được mô tả trong bài viết này. Đối với các ví dụ trong tài liệu này, tên Máy chủ được Liên kết (mà bạn tham chiếu trong các lệnh SQL của mình) được sử dụng là SF8.
Tất cả SQL trong tài liệu này đã được kiểm tra dựa trên SQL Server 2017 và trình điều khiển Easysoft Salesforce ODBC phiên bản 2.0.0 đến 2.0.7.
Các chức năng của SQL Server OPENQUERY
và EXEC
(EXECUTE
) đã được đưa vào SQL Server 2008 và các chức năng này tương thích với tất cả các phiên bản của SQL Server sau năm 2008.
Chúng tôi đã viết tài liệu này để đáp lại một số truy vấn mà Nhóm hỗ trợ của chúng tôi nhận được liên quan đến việc kết nối SQL Server thông qua Easysoft với Salesforce. Tuy nhiên, các ví dụ SQL cũng sẽ hữu ích cho các kết nối Máy chủ được Liên kết sử dụng trình phụ trợ và trình điều khiển ODBC khác.
Nếu bạn muốn đóng góp cho tài liệu này, vui lòng gửi email đến.
Mệnh đề WHERE
Một vấn đề phổ biến được báo cáo cho chúng tôi là "Một mệnh đề WHERE đơn giản mất nhiều thời gian để trả về chỉ một hàng". Ví dụ:
select Id, FirstName, LastName from SF8.SF.DBO.Contact where Id='00346000002I95MAAS'
SQL Server chuyển đổi truy vấn trên và gửi điều này đến trình điều khiển Salesforce ODBC:
select Id, FirstName, LastName from SF.DBO.Contact
Mệnh đề WHERE luôn bị loại bỏ, điều này buộc trình điều khiển ODBC trả về tất cả các hàng cho bảng đó. Sau đó, SQL Server lọc chúng cục bộ để cung cấp cho bạn (các) hàng cần thiết. Có vẻ như điều khoản WHERE bạn đã chỉ định không quan trọng, điều này không bao giờ được chuyển cho trình điều khiển ODBC.
Giải pháp đơn giản cho việc này là sử dụng SQL Server OPENQUERY
chức năng thay thế. Ví dụ:
select * from OPENQUERY(SF8,'select Id, FirstName, LastName from SF.DBO.Contact where Id=''00346000002I95MAAS'' ')
Tất cả SQL bạn chạy bên trong OPENQUERY
hàm được chuyển thẳng tới trình điều khiển, bao gồm WHERE
mệnh đề.
Nhiều bảng tham gia
Đây là một phép nối hai bảng đơn giản trong đó cả hai bảng đều quay trở lại từ máy chủ được liên kết.
select a.[Name], BillingStreet, c.[Name] from SF8.SF.DBO.Account a, SF8.SF.DBO.Contact c where a.Id=c.AccountID and a.[Name] like 'United%'
SQL Server gửi các truy vấn sau đến trình điều khiển ODBC.
select * from Account select * from Contact
SQL Server thực hiện việc này để nhận danh sách tên cột và kiểu dữ liệu. Sau đó, nó tiếp tục gửi các truy vấn này đến trình điều khiển ODBC.
SELECT "Tbl1001"."Id" "Col1042","Tbl1001"."Name" "Col1044","Tbl1001"."BillingStreet" "Col1046" FROM "SF"."DBO"."Account" "Tbl1001" ORDER BY "Col1042" ASC SELECT "Tbl1003"."AccountId" "Col1057","Tbl1003"."Name" "Col1058" FROM "SF"."DBO"."Contact" "Tbl1003" ORDER BY "Col1057" ASC
Dữ liệu từ cả hai truy vấn được trả về các bảng cục bộ, sau đó mệnh đề WHERE được đặt trên bảng Tài khoản và dữ liệu từ cả hai bảng được kết hợp và trả về.
Một lần nữa việc sử dụng OPENQUERY
đảm bảo SQL bạn viết được chuyển trực tiếp đến trình điều khiển ODBC, do đó, thay vào đó, trong SQL Server bạn sẽ chạy:
select * from OPENQUERY(SF8,'select a.[Name], BillingStreet, c.[Name] from SF.DBO.Account a, SF.DBO.Contact c where a.Id=c.AccountID and a.[Name] like ''United%'' ')
Bạn cần sửa đổi một chút, vì SQL Server không thể xử lý nhiều cột có cùng "Tên", vì vậy bạn cần đổi tên một trong các cột đó. Ví dụ:
select * from OPENQUERY(SF8,'select a.[Name], BillingStreet, c.[Name] as FullName from SF.DBO.Account a, SF.DBO.Contact c where a.Id=c.AccountID and a.[Name] like ''United%'' ')
Điều này buộc trình điều khiển ODBC xử lý toàn bộ SQL trong một lần và chỉ trả về kết quả được yêu cầu.
Bảng cục bộ được đính kèm với bảng từ xa
Trong ví dụ này, bảng cục bộ được tạo bằng cách chạy.
select * into LocalAccount from SF8.SF.DBO.Account
Sự kết hợp của hai bảng bây giờ trông như thế nào.
select a.[Name], BillingStreet, c.[Name] as FullName from LocalAccount a, SF8.SF.DBO.Contact c where a.Id=c.AccountID and a.[Name] like 'United%'
Điều này khiến SQL Server gửi truy vấn sau ba lần tới trình điều khiển ODBC.
select * from Contact
Trong ít nhất một trong các truy vấn đó, SQL Server yêu cầu tất cả dữ liệu trong bảng. Sau đó, SQL Server tiếp tục yêu cầu:
SELECT "Tbl1003"."Name" "Col1008" FROM "SF"."DBO"."Contact" "Tbl1003" WHERE ?="Tbl1003"."AccountId"
Sau đó, SQL Server chuyển đến trình điều khiển ODBC một danh sách AccountIds từ bảng LocalAccount thay cho dấu "?" tham số trong đó cột LocalAccount. [Name] khớp với mệnh đề LIKE.
Một cách nhanh hơn trong đó bảng ODBC là bảng thứ hai trong truy vấn, là chỉ lấy các cột bạn cần từ bảng ODBC. Điều này có thể được thực hiện bằng cách sử dụng OPENQUERY
hàm số. Ví dụ:
select a.[Name], BillingStreet, c.[Name] as FullName from LocalAccount a, openquery(SF8,'select [Name], AccountId from SF.DBO.Contact') c where a.Id=c.AccountID and a.[Name] like 'United%'
Trong khi điều này vẫn lấy tất cả các hàng từ bảng Liên hệ, nó chỉ lấy các cột cần thiết và do đó nhanh hơn truy vấn tiêu chuẩn.
Một cách khả thi khác là sử dụng con trỏ và bảng tạm thời. Ví dụ:
Begin declare @AccountId as varchar(20) declare @SQL as varchar(1024) -- Create a temporary table to store the Account information. The Id check ensures 0 rows of data are returned select * into #LocalContact from openquery(SF8,'select [Name], AccountId from SF.DBO.Contact where Id=''000000000000000000'' ') -- Set up the cursor declare selcur cursor for select distinct Id from LocalAccount where [Name] like 'United%' open selcur fetch next from selcur into @AccountId while @@FETCH_STATUS=0 Begin select @SQL ='insert into #LocalContact select [Name], '''+@AccountId+''' from OPENQUERY(SF8,''select [Name] from Contact where AccountId=''''' + @AccountId + ''''' '')' exec (@SQL) fetch next from selcur into @AccountId End close selcur deallocate selcur -- Next, join your tables and view the data select a.[Name], BillingStreet, c.[Name] as FullName from LocalAccount a, #LocalContact c where a.Id=c.AccountID and a.[Name] like 'United%' -- Don't forget to remove the temporary table drop table #LocalContact End
Phương pháp này có thể nhanh hơn nhiều lần so với OPENQUERY
được hiển thị trong ví dụ trước, nếu mệnh đề WHERE được chuyển đến trình điều khiển Easysoft ODBC sử dụng một chỉ mục trong Salesforce.
Chèn, Cập nhật và Xóa
Nếu bạn đang chạy một truy vấn không phải là một truy vấn CHỌN thì cách tốt nhất để thực hiện việc này là sử dụng SQL Server EXEC
hàm số. Nếu máy chủ được liên kết của bạn không thể sử dụng EXEC
, bạn sẽ nhận được một thông báo tương tự như:
Server 'SF8' is not configured for RPC.
Để sử dụng EXEC
, nhấp chuột phải vào máy chủ được liên kết của bạn và chọn thuộc tính. Trong phần "Tùy chọn máy chủ", đặt "RPC Out" thành "True". Sau đó, bạn có thể sử dụng EXEC
chức năng.
Cập nhật
Giả sử bạn có câu lệnh này trong SQL Server:
UPDATE SF8.SF.DBO.Contact SET LastName='James' WHERE Id='00346000002I95MAAS'
Máy chủ SQL gửi SQL này tới trình điều khiển ODBC.
select * from "SF"."DBO"."Contact"
Tất cả các bản ghi được truy xuất và SQL Server sau đó sẽ gửi câu lệnh này đến trình điều khiển ODBC.
UPDATE "SF"."DBO"."Contact" SET "LastName"=? WHERE "Id"=? AND "LastName"=?
SQL Server đang làm điều đó để đảm bảo rằng bản ghi không bị thay đổi giữa thời gian bạn chạy truy vấn và thời gian CẬP NHẬT được thực thi. Một phương pháp nhanh hơn là sử dụng SQL Server EXEC
hàm số. Ví dụ:
exec ('update SF.DBO.Contact set LastName=''James'' where Id=''00346000002I95MAAS''' ) at SF8
SQL Server gửi cho trình điều khiển ODBC toàn bộ chuỗi bạn đã nhập, do đó, truy vấn được thực thi mà không cần chọn toàn bộ bảng.
Cập nhật với các Tham số
Giả sử bạn có:
Begin declare @Id varchar(20)='00346000002I95MAAS' declare @LastName varchar(20)='James' update SF8.SF.DBO.Contact set LastName=@LastName where Id=@Id End
Điều này hoạt động chính xác theo cách giống như được mô tả trong ghi chú Cập nhật. Tuy nhiên, cú pháp khi sử dụng EXEC
thay đổi chức năng:
Begin declare @Id varchar(20)='00346000002I95MAAS' declare @LastName varchar(20)='James' exec ('update SF.DBO.Contact set LastName=? where Id=?', @LastName, @Id) at SF8 End
Nơi bạn có một cột chẳng hạn như LastName=
bạn đặt một ?
thay cho @LastName
đại diện cho những gì bạn sẽ truyền vào tham số. Các tham số sau đó được liệt kê sau câu lệnh UPDATE theo thứ tự mà chúng cần được đọc.
Chèn bản ghi mới và gặp lỗi BLOB
Giả sử bạn đang cố gắng chạy:
insert into SF8.SF.DBO.Contact ( FirstName, LastName ) values ('Easysoft','Test')
SQL Server gửi điều này đến trình điều khiển ODBC:
select * from "SF"."DBO"."Contact"
Điều này được thực hiện hai lần. Lần đầu tiên điều này được chạy, SQL Server đang kiểm tra xem tập kết quả có thể cập nhật được hay không. Lần thứ hai điều này được gửi, SQL Server di chuyển đến một bản ghi trống sau khi bản ghi cuối cùng được trả lại và cố gắng thực hiện một INSERT vị trí, điều này gây ra lỗi.
OLE DB provider "MSDASQL" for linked server "SF8" returned message "Query-based insertion or updating of BLOB values is not supported.".
Thông báo này được trả lại vì một chèn vị trí cố gắng chèn tất cả các cột có giá trị NULL ngoại trừ những cột bạn đã chỉ định trong câu lệnh INSERT của mình và trong trường hợp của bảng Liên hệ, có một BLOB (Vùng Văn bản Dài trong Salesforce), mà Nhà cung cấp OLE DB của Microsoft không hỗ trợ. Trình điều khiển Easysoft Salesforce ODBC hỗ trợ chèn tất cả các trường trong Salesforce mà bạn có quyền chèn dữ liệu. Để giải quyết vấn đề này, tất cả những gì bạn cần làm là sử dụng EXEC.
Các giá trịexec ('insert into SF.DBO.Contact ( FirstName, LastName ) values (''Easysoft'',''Test'')') at SF8
Điều này chỉ gửi INSERT thẳng đến trình điều khiển ODBC.
Lấy Id Salesforce cho Bản ghi Cuối cùng Bạn đã Chèn
Một số khách hàng của chúng tôi đã hỏi phương pháp dễ nhất để lấy Id của hàng vừa được chèn vào. Ví dụ này cho thấy cách bạn có thể lấy Id của bản ghi cuối cùng bạn đã chèn vào bảng "Liên hệ".
Begin declare @Id varchar(20)='00346000002I95MAAS' declare @FirstName varchar(20)='Easysoft' declare @LastName varchar(20)='Test' declare @FindTS varchar(22)=convert(varchar(22),GETUTCDATE(),120) declare @SQL as varchar(1024) exec ('insert into SF.DBO.Contact (FirstName, LastName ) values (?, ?)', @FirstName, @LastName ) at SF8 select @SQL='select Id from openquery(SF8, ''select top 1 c.Id from [User] u, Contact c where u.Username=CURRENT_USER and c.CreatedDate>={ts '''''+@FindTS+'''''} and c.CreatedById=u.Id order by c.CreatedDate desc'')' exec (@SQL) End
Khi bản ghi được tạo trong Salesforce, cột "Ngày tháng năm" chứa dấu thời gian là UTC (Giờ phối hợp quốc tế) mà bản ghi đã được tạo và không nhất thiết phải là ngày / giờ hiện tại của bạn. @FindTs
chuỗi được đặt thành UTC trước khi INSERT diễn ra, vì vậy khi SELECT để lấy Id được gọi, nó chỉ xem xét các hàng được chèn sau @FindTS
đã được thiết lập.
Trong quá trình CHỌN, CURRENT_USER
của Easysoft hàm cũng được sử dụng để giới hạn các hàng được trả về từ Salesforce chỉ cho người dùng đã chèn dữ liệu.
Cập nhật Dữ liệu Máy chủ SQL khi Dữ liệu Salesforce Thay đổi
Phần này chỉ cho bạn cách tạo bảng SQL Server mới dựa trên cấu trúc của bảng Salesforce và cập nhật bảng đó khi có những thay đổi trong bảng Salesforce đó.
create procedure SFMakeLocal( @Link varchar(50), @Remote varchar(50), @Local varchar(50), @DropLocal int) as declare @SQL as nvarchar(max) begin /* Imports the data into a local table */ /* Set DropLocal to 1 to drop the local table if it exists */ if OBJECT_ID(@Local, 'U') IS NOT NULL begin if (@DropLocal=1) begin set @SQL='DROP TABLE dbo.'+@Local exec ( @SQL) end else RAISERROR(15600,1,1, 'Local table already exists') RETURN end set @SQL='select * into dbo.'+@Local+' from OPENQUERY('+@Link+',''select * from '+@Remote+''')' exec(@SQL) select 'Local Table :'+@Local+' created.' end -- @Link Your SQL Server linked server -- @Remote The name of the table within Salesforce -- @Local The local table you want the data to be stored in -- @DropLocal Set to 1 if the table exists and you want to drop it
Chạy quy trình để sao chép cấu trúc bản ghi từ bảng Salesforce vào bảng cục bộ và sau đó chuyển tất cả dữ liệu Salesforce. Lệnh ví dụ này sử dụng bảng Tài khoản. Quá trình này có thể mất khá nhiều thời gian tùy thuộc vào lượng dữ liệu bạn có trong bảng Salesforce.
SFMakeLocal 'SF8','Account','LocalAccount', 0
Các đối số là:
Đối số | Giá trị |
---|---|
SF8 | Tên máy chủ được liên kết của SQL Server. |
Tài khoản | Tên bảng Salesforce bạn muốn sử dụng để đọc cấu trúc và dữ liệu từ đó. |
LocalAccount | Tên bảng của bạn trong SQL Server. |
0 | Giá trị mặc định này có thể được thay đổi thành 1 nếu bạn thêm nhiều cột tùy chỉnh hơn vào Salesforce và bạn muốn bỏ bảng cục bộ để tạo lại nó với các cột mới. |
Bước tiếp theo là tạo thêm hai quy trình sẽ cập nhật bảng cục bộ nếu bất kỳ dữ liệu nào được cập nhật hoặc chèn vào bảng Salesforce:
create procedure SFUpdateTable ( @Link varchar(50), @Remote varchar(50), create procedure SFUpdateTable @Link varchar(50), @Remote varchar(50), @LocalTable varchar(50) as begin -- Updates the data into a local table based on changes in Salesforce. declare @TempDef as varchar(50)='##EasyTMP_' declare @TempName as varchar(50) declare @TempNumber as decimal declare @CTS as datetime=current_timestamp declare @TTLimit int = 100 declare @MaxCreated as datetime declare @MaxModified as datetime declare @SQL as nvarchar(max) declare @RC as int -- The first step is to create a global temporary table. set @TempNumber=datepart(yyyy,@CTS)*10000000000+datepart(mm,@CTS)*100000000+datepart(dd,@CTS)*1000000+datepart(hh,@CTS)*10000+datepart(mi,@CTS)*100+datepart(ss,@CTS) set @TempName=@TempDef+cast(@TempNumber as varchar(14)) while OBJECT_ID(@TempName, 'U') IS NOT NULL begin RAISERROR (15600,1,1, 'Temp name already in use.') RETURN end set @SQL='select * into '+@TempName+' from '+@LocalTable+' where 1=0' create table #LocalDates ( ColName varchar(20), DTS datetime) set @sql='insert into #LocalDates select ''Created'', max(CreatedDate) from '+@LocalTable exec (@sql) set @sql='insert into #LocalDates select ''Modified'', max(LastModifiedDate) from '+@LocalTable exec (@sql) select @MaxCreated=DTS from #LocalDates where ColName='Created' select @MaxModified=DTS from #LocalDates where ColName='Modified' drop table #LocalDates set @SQL='select * into '+@TempName+' from openquery('+@Link+',''select * from '+@Remote+' where CreatedDate>{ts'''''+convert(varchar(22),@MaxCreated,120)+'''''}'')' exec(@SQL) exec SFAppendFromTemp @LocalTable, @TempName set @SQL='drop table '+@TempName exec (@SQL) set @SQL='select * into '+@TempName+' from openquery('+@Link+',''select * from '+@Remote+' where LastModifiedDate>{ts'''''+convert(varchar(22),@MaxModified,120)+'''''} and CreatedDate<={ts'''''+convert(varchar(22),@MaxCreated,120)+'''''}'')' exec (@SQL) exec SFAppendFromTemp @LocalTable, @TempName set @SQL='drop table '+@TempName exec (@SQL) end create procedure SFAppendFromTemp(@Local varchar(50), @TempName varchar(50)) as begin /* Uses the temp table to import the data into the local table making sure any duplicates are removed first */ declare @Columns nvarchar(max) declare @ColName varchar(50) declare @SQL nvarchar(max) set @sql='delete from '+@Local+' where Id in ( select Id from '+@TempName+')' exec (@SQL) set @Columns='' declare col_cursor cursor for select syscolumns.name from sysobjects inner join syscolumns on sysobjects.id = syscolumns.id where sysobjects.xtype = 'u' and sysobjects.name = @Local open col_cursor fetch next from col_cursor into @ColName while @@FETCH_STATUS=0 Begin set @Columns=@Columns+'['+@ColName+']' fetch next from col_cursor into @ColName if (@@FETCH_STATUS=0) set @Columns=@Columns+', ' End close col_cursor deallocate col_cursor set @sql='insert into '+@Local+' (' +@Columns+') select '+@Columns+' from '+@TempName exec (@sql) end -- Two procedures are used to get the data from a remote table. 1) SFUpdateTable, which -- copies the data into a temporary table. 2) SFAppendFromTemp, which appends -- the data from the temporary table into the local table. -- @Link Your SQL Server linked server name -- @Remote The name of the table within Salesforce -- @Local The local table where you want the data to be stored in -- @TempName A name of a table that can be used to temporary store data. Do not -- use an actual temporary table name such as #temp, this will not work.
Để kiểm tra điều này, hãy chạy:
SFUpdateTable 'SF8','Account','LocalAccount'
Ví dụ này có thể được sử dụng với bất kỳ bảng Salesforce nào mà người dùng có quyền truy cập.
Xác thực giản đồ lười biếng
Trong thuộc tính máy chủ liên kết SQL Server của bạn, trong phần "Tùy chọn máy chủ", là một tùy chọn cho "Xác thực lược đồ lười biếng". Theo mặc định, điều này được đặt thành FALSE, khiến SQL Server gửi câu lệnh SELECT hai lần. Lần đầu tiên truy vấn được gửi, SQL Server sử dụng các chi tiết được trả lại để xây dựng siêu dữ liệu về tập kết quả của bạn. Sau đó, truy vấn được gửi lại. Đây là một chi phí khá tốn kém, vì vậy Easysoft khuyên bạn nên đặt "Xác thực lược đồ lười biếng" thành TRUE, có nghĩa là chỉ một truy vấn được gửi, truy xuất cả siêu dữ liệu và tập kết quả trong một lần. Điều này cũng giúp tiết kiệm số lượng lệnh gọi API Salesforce được thực hiện.
Hạn chế của OLEDB của Microsoft dành cho Nhà cung cấp ODBC
Thông tin chi tiết về các hạn chế của OLEDB dành cho Nhà cung cấp ODBC có thể được tìm thấy tại:
https://msdn.microsoft.com/en-us/library/ms719628(v=vs.85).aspx
Làm cách nào để tìm các bản ghi có nguồn cấp dữ liệu dòng (dòng mới) trong địa chỉ thanh toán?
Bằng cách sử dụng một số chức năng bên trong của trình điều khiển Easysoft, bạn có thể dễ dàng tìm thấy các bản ghi trong đó địa chỉ thanh toán có nguồn cấp dữ liệu dòng trong bản ghi. Ví dụ:
select * from openquery(sf8,'select Id, Name, {fn POSITION({fn CHAR(10)} IN BillingStreet)} LinePos from Account where {fn POSITION({fn CHAR(10)} IN BillingStreet)} >0')
POSITION(x)
Hàm này tìm kiếm vị trí của x
trong cột được chỉ định.
CHAR(X)
Hàm này trả về ký tự có giá trị ASCII là x
.
Thông tin thêm về các chức năng có sẵn trong trình điều khiển Salesforce ODBC của chúng tôi có thể được tìm thấy tại đây
Tôi có thể xem bảng nào có sẵn thông qua phần mềm Easysoft không?
Để có danh sách các bảng mà bạn có thể truy cập, hãy chạy:
select * from openquery(SF8,'select TABLE_NAME from INFO_SCHEMA.TABLES')
Tôi có thể xem những cột nào có sẵn thông qua phần mềm Easysoft không?
Bạn có thể lấy danh sách các cột trong bảng bằng cách chạy:
select * from openquery (SF8, 'select * from INFO_SCHEMA.COLUMNS where TABLE_NAME =' 'Account' '')
Sử dụng phương pháp này, bạn chỉ có thể nhận được danh sách các cột thuộc bảng mà bạn chỉ định trong mệnh đề TABLE_NAME WHERE. Nếu bạn muốn xem danh sách đầy đủ các cột cho tất cả các bảng, hãy chạy:
begin declare @Table nvarchar(max) declare table_cursor cursor for select TABLE_NAME from openquery(SF8,'select TABLE_NAME from INFO_SCHEMA.TABLES') open table_cursor fetch next from table_cursor into @Table while @@FETCH_STATUS=0 Begin exec ('select * from INFO_SCHEMA.COLUMNS where TABLE_NAME=?', @Table) at SF8 fetch next from table_cursor into @Table End close table_cursor deallocate table_cursor end
Tôi có thể tạo một máy chủ được liên kết theo chương trình không?
Đúng. Có rất nhiều ví dụ về điều này trên web, ví dụ:
http://www.sqlservercentral.com/articles/Linked+Servers/142270/?utm_source=SSC