--查詢表
select * from openrowset('SQLOLEDB', 'IP'; 'sa'; '密碼',數據庫名稱.dbo.表名稱)
--查詢存儲
--示例1
select * from openrowset('SQLOLEDB', 'SERVER=IP;uid=sa;pwd=密碼;Database=數據庫名稱','SET FMTONLY OFF;SET NOCOUNT ON exec 存儲過程名稱 ''165'' ,''2019-11-23'' ,''''')
--示例2
select * from openrowset('SQLOLEDB', 'SERVER=IP;uid=sa;pwd=密碼;Database=數據庫名稱','SET FMTONLY OFF;SET NOCOUNT ON exec 存儲過程名稱 ''162'' ,''2019-11-23'' ,''''')
你可能常常會需要運行一個ad hoc查詢從遠程OLE DB數據源提取數據,或者批量向SQL Server表導入數據。在這種情況下,你可以在T-SQL(Transact-SQL,微軟對SQL的擴展)中用OPENROWSET函數給數據源傳入 一個連接串和查詢來提取需要的數據。 你可以使用OPENROWSET函數從任何支持注冊OLE DB的數據源獲取數據,比如從SQL Server或Access的遠程實例中提取數據。如果你用OPENROWSET從SQL Server實例中獲取數據,該實例必須配置為允許ad hoc分布式查詢。
要配置遠程SQL Server實例支持ad hoc查詢,需要使用系統存儲過程sp_configure先設置advanced options,再啟用Ad Hoc Distributed Queries(ad hoc分布式查詢)。請看下面的T-SQL腳本:
EXEC sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO
EXEC sp_configure 'Ad Hoc Distributed Queries', 1
GO
RECONFIGURE;
GO
要注意的是,在運行完存儲過程之后,你必須運行“RECONFIGURE”命令。
一旦你配置好了遠程SQL Server實例,你就可以對它使用OPENROWSET函數。這個函數可以在SELECT語句的FROM從句里使用。下面的例子顯示了該函數的基本語法:
OPENROWSET('provider', 'connection string', target)
可以看到,這個函數有三個參數:
•provider —— 某特定數據源支持的OLE DB提供者的人機友好名稱(ProgID)。Provider的名字必須用單引號括起來。
•Connection string —— 連接串。它是與具體提供者provider相關的字符串,包括連接到給字符串中指定的數據源所需要的細節信息。根據provider的不同,連接串信息需要用一對或多對單引號括起來。
•Target —— target參數可以使一個數據庫對象或者一個查詢。
Object —— 數據庫對象的名字,比如表或者視圖的名稱。對象的完整名字必須提供,它們不需要用單引號括起來。
Query —— query是從遠程數據源提取數據的Select語句。Query必須用單引號括起來。
下面的例子展示了OPENROWSET函數的用法:
SELECT Employees.*
FROM
OPENROWSET(
'SQLNCLI',
'Server=SqlSrv1;Trusted_Connection=yes',
'SELECT EmployeeID, FirstName, LastName, JobTitle
FROM AdventureWorks.HumanResources.vEmployee
ORDER BY LastName, FirstName'
) AS Employees
注意該Select語句的FROM從句中使用了OPENROWSET函數和3個參數。第一個參數SQLNCLI是SQL Server OLE DB提供者的名稱。
這樣我們就可以使用OPENROWSET函數了。函數返回一個結果集(我把它用AS命名為“Employees”),From使用該結果集的方式與使用其他普通查詢的方式一樣。
我們在上面提到,你也可以從SQL Server以外的數據源提取數據。例如:下面的Select語句查詢微軟Access數據庫的Employees表。
SELECT Employees.*
FROM
OPENROWSET(
'Microsoft.Jet.OLEDB.4.0',
'C:\Data\Employees.mdb';'admin';'
',
'SELECT EmployeeID, FirstName, LastName, JobTitle
FROM Employees
ORDER BY LastName, FirstName'
) AS Employees
你可能注意到了,這次的provider不同於我們在訪問SQL Server時使用的Provider。在本例中,Provider是Microsoft.Jet.OLEDB.4.0(注意:對於Access 2007,有新的Provider可用)。
連接串與前面例子中的寫法也不一樣。整個連接串從頭到尾分成了三部分,每一部分都被單引號單獨括起來,各部分之間用分號分割。
第一部分指定了Access數據庫文件的路徑和文件名,后面緊跟着是用戶賬號admin(Access數據庫內部的管理員賬號)。第三部分是一個空字 符串,是Access數據庫的密碼。因為admin賬號沒有設定密碼,所以使用空字符串。如果該賬號設置了密碼,應該把密碼寫在第三部分。
整個連接串與后面用來從Access數據庫查詢數據的Select語句用逗號“,”隔開。(我在Access中使用的Employees表是從SQL Server的vEmployee視圖導入的)
這就是從Access數據庫查詢數據要做的全部事情。你的查詢會返回一個結果集,該結果集與訪問本地SQL Server數據庫時得到的結果集類似。
你也可以使用OPENROWSET函數從多個數據源中查詢數據。例如:下面的例子我使用inner join(內連接)從遠程SQL Server實例和Access數據庫查詢數據。
SELECT e1.EmployeeID, e2.FirstName, e2.LastName, e1.JobTitle
FROM
OPENROWSET(
'SQLNCLI',
'Server=SqlSrv1;Trusted_Connection=yes;',
'SELECT EmployeeID, FirstName, LastName, JobTitle
FROM AdventureWorks.HumanResources.vEmployee'
) AS e1
INNER
JOIN
OPENROWSET(
'Microsoft.Jet.OLEDB.4.0',
'C:\Data\Employees.mdb'; 'admin';'
',
'SELECT EmployeeID, FirstName, LastName, JobTitle
FROM Employees'
) AS e2
ON e1.EmployeeID = e2.EmployeeID
ORDER
BY e2.LastName, e2.FirstName
注意:外層的Select語句從兩個表返回數據——從SQL Server返回員工ID和工作頭銜,從Access數據庫返回姓和名。由於你可以得到可靠的連接查詢,盡管你是從本地SQL Server實例連接表中查詢的數據,你可以處理這些數據。
現在我們來看看OPENROWSET函數的另一個重要功能——批量導入。為了舉例需要,我在AdventureWorks數據庫中用下面的腳本創建了表Employees並導入數據。
USE AdventureWorks
GO
IF
OBJECT_ID (N'Employees', N'U') IS
NOT
NULL
DROP
TABLE dbo.Employees
GO
SELECT EmployeeID, FirstName, LastName, JobTitle
INTO Employees
FROM HumanResources.vEmployee
GO
ALTER
TABLE Employees
ADD ResumeFile VARBINARY(MAX) NULL
GO
注意:我沒有把ResumeFile列的數據導入,它的數據類型是VARBINARY(MAX)。我會用下面的Update語句把Employee1.docx文件作為二進制數據批量導入到該列。
USE AdventureWorks
GO
UPDATE Employees
SET ResumeFile = (
SELECT
*
FROM
OPENROWSET(BULK
'C:\Data\Employee1.docx', SINGLE_BLOB)
AS ResumeContent)
WHERE EmployeeID =
1
可以看到,OPENROWSET函數提供了BULK選項,你可以用它來導入數據。要使用BULK選項,需要指定你想要導入的文件,並指定導入方式。既 然我想把文件以二進制形式導入,我在上面的例子中使用了SINGLE_BLOB選項。當然,如果該列支持字符型數據,我也可以用SINGLE_CLOB或 者SINGLE_NCLOB選項指定數據 存儲為字符類型格式。此外,在使用OPENROWSET函數批量導入數據功能時,你也可以使用格式化的文件,不過關於格式化文件的用法超出了本文討論的范圍。