目錄
- WinCC歸檔數據庫介紹
- 安裝ConnectivityPack
- 在SQL Server中通過鏈接服務器訪問歸檔數據庫
- 在SQL Server中通過OPENDATASOURCE訪問歸檔數據庫
- 通過存儲過程訪問歸檔數據庫
- 重新排列數據
- 用VB腳本訪問歸檔數據庫
- 訪問另一台電腦的WinCC歸檔數據庫
WinCC歸檔數據庫介紹
WinCC的歷史工藝數據和報警消息保存在SQL Server數據庫,數據以分段和壓縮形式儲存,不方便直接通過SQL去讀取,用WinCC OLE DB Provider訪問這些數據時會自動合並分段並解壓縮數據。
安裝ConnectivityPack
WinCC OLE DB provider由WinCC的ConnectivityPack選件提供,在安裝WinCC時需要安裝ConnectivityPack。在提供數據的WinCC的計算機需安裝ConnectivityPack server,讀取數據的計算機上安裝ConnectivityPack client,可以在計算機上同時安裝ConnectivityPack server和ConnectivityPack client。

在SQL Server中通過鏈接服務器訪問歸檔數據庫
創建鏈接服務器
安裝了WinCC的計算機中,啟動WinCC項目時會自動創建鏈接服務器。在未安裝WinCC的計算機需要手動創建鏈接服務器。
打開SQL Server Management Studio,在對象資源管理器中,展開“服務器對象”,右鍵單擊“鏈接服務器”,然后單擊“新建鏈接服務器”。

如下圖填入鏈接服務器信息,數據源(Data Source)中填入WinCC服務器的數據庫完整實例名,目錄(Catalog)中填入歸檔數據庫名。


使用OPENQUERY查詢連接服務器
查詢鏈接數據庫使用OPENQUERY,傳遞給OPENQUERY查詢語句不同於SQL,是WinCC的特定查詢語句,可通過變量ID或變量名查詢。如下:
select * from openquery(LnkRtDb_WinCCOLEDB,'Tag:R,1,''0000-00-00 01:00:00.000'',''0000-00-00 00:00:00.000''')
使用變量ID查詢:

使用變量名查詢:

在SQL Server中通過OPENDATASOURCE訪問歸檔數據庫
通過OPENDATASOURCE()函數可直接查詢OLE DB數據源,語法如下:
SELECT *
FROM OPENDATASOURCE('WinCCOleDbProvider.1',
'Provider=WinCC OLEDB Provider for Archives;
Catalog=CC_WinCCSer_19_02_14_10_59_03R;
Data Source=WIN-54UD17PRU0N\WINCC').
N'Tag:R,1,''0000-00-00 00:10:00.000'',''0000-00-00 00:00:00.000'''

通過存儲過程訪問歸檔數據庫
存儲過程(Stored Procedure)是在大型數據庫系統中,一組為了完成特定功能的SQL 語句集,它存儲在數據庫中,一次編譯后永久有效,用戶通過指定存儲過程的名字並給出參數(如果該存儲過程帶有參數)來執行它。
適用於WinCC歸檔數據庫的存儲過程有哪些
如下圖的路徑,在System Databases -> master數據庫下有部分存儲過程,在WinCC項目程序對應的數據庫下也有部分存儲過程。

大部分存儲過程都找不到對應的使用說明,下面對已知的幾個存儲過程簡單介紹。
cp_TagStatistic
cp_TagStatistic是對過程值統計分析的存儲過程,它的使用方法在官方文檔中有描述。
CC_SP_ReadTags
是一個讀取過程值的存儲過程,查詢到的值會被存儲到一個臨時表中。
在SQL Server中CC_SP_ReadTags源代碼是被加密的,從網絡上查到的源代碼如下,僅做參考:
USE CC_SIR_16_07_29_11_30_35R
GO
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER OFF
GO
CREATE PROCEDURE [dbo].[CC_SP_ReadTags]
(
@List varchar(1000),
@TimeBegin varchar(32),
@TimeEnd varchar(32),
@WHEREClause varchar(1000)= NULL,
@ORDERBYClause varchar(1000) = NULL,
@Timestep varchar(500) = NULL,
@Aggregationmode int = 0,
@SymDataSource varchar(512) = NULL,
@SymCatalog varchar(512) = NULL,
@LS_Name varchar(255)=NULL
)
WITH encryption
AS
BEGIN
SET NOCOUNT ON
--DECLARE @LS_Name varchar(255)
DECLARE @Catalogname varchar(255)
DECLARE @Internal_LS bit
DECLARE @NoTime bit
SET @Internal_LS = 0
-- check valid datetime or Aggregationmode = 0
DECLARE @ret int
SET @ret = ISDATE(@TimeBegin)
IF (@ret = 0 and @Aggregationmode <> 0)
RETURN
IF ISNULL(@LS_Name,'') = ''
BEGIN
SET @LS_Name = 'CA_'+ CAST(@@SPID as varchar(10))
SET @Catalogname = DB_NAME()
if @SymDataSource = NULL
set @SymDataSource = 'Hallo'
if ISNULL(@SymDataSource,'') = '' or ISNULL(@SymCatalog,'') = ''
BEGIN
EXEC sp_addlinkedserver @server = @LS_Name,@srvproduct = 'CommonArchiving', @provider = 'WinCCOLEDBProvider', @datasrc = @@servername, @catalog = @CatalogName
set @Internal_LS = 1
END
ELSE
BEGIN
EXEC sp_addlinkedserver @server = @LS_Name,@srvproduct = 'CommonArchiving', @provider = 'WinCCOLEDBProvider', @datasrc = @SymDataSource, @catalog = @SymCatalog
set @Internal_LS = 1
END
END
DECLARE @Statement varchar(8000)
SET @Statement = ''
SET @Statement = 'SELECT * FROM OPENQUERY('+@LS_Name+',''Tag:R,('+@List+'),'''''+@TimeBegin+''''','''''+@TimeEnd+''''''
IF(LEN(@TimeStep) <> 0)
BEGIN
SET @Statement = @Statement + ',' + @Timestep + ',' + CAST(@Aggregationmode AS VARCHAR(6))
END
SET @Statement = @Statement + ' '') '
IF(LEN(@WHEREClause) <> 0)
BEGIN
SET @Statement = @Statement + @WHEREClause
END
IF(LEN(@ORDERBYClause) <> 0)
BEGIN
SET @Statement = @Statement + ' ORDER BY ' + @ORDERBYClause
END
--print @Statement
BEGIN
EXEC( @Statement )
END
if @Internal_LS = 1
BEGIN
EXEC sp_dropserver @server = @LS_Name
set @LS_Name = NULL
END
SET NOCOUNT OFF
END
GO


CC_SP_ReadTags的參數說明如下:
| 參數 |
說明 |
| @List |
變量列表 |
| @TimeBegin |
查詢的起始時間 |
| @TimeEnd |
結束時間 |
| @WHEREClause |
過濾條件 |
| @ORDERBYClause |
排序 |
| @Timestep |
時間間隔(以秒計),格式為’TimeStep=60’ |
| @Aggregationmode |
匯總類型(定義時間間隔結果) |
| @TempTable |
臨時表名稱,默認值為“TlgDataTmp” |
| @SymDataSource |
建立鏈接服務器的數據源 |
| @SymCatalog |
建立鏈接服務器的數據目錄 |
| @LS_Name |
指定要使用的鏈接服務器 |
語句示例:
USE [CC_WinCCSer_19_02_14_10_59_03R]
GO
IF OBJECT_ID('tempdb..##TagsTempTable') is not NULL
DROP Table ##TagsTempTable
DECLARE @return_value int
EXEC @return_value = [dbo].[CC_SP_ReadTags]
@List = N'archive1\tag1;archive1\tag2',
@TimeBegin = N'0000-00-00 00:01:00',
@TimeEnd = N'0000-00-00 00:00:00',
@WHEREClause = default,
@ORDERBYClause = default,
@Timestep = default,
@Aggregationmode = default,
@TempTable = N'##TagsTempTable',
@SymDataSource = default,
@SymCatalog = default,
@LS_Name = N'LnkRtDb_WinCCOLEDB'
SELECT 'Return Value' = @return_value
GO

重新排列數據
上面的示例圖片中查詢出的數據是以列的形式排序的,通過下面代碼可以把相同時間戳的數據放在同一行。
declare @TimeBegin datetime = '2020-09-03 00:00:00.000';
declare @TimeEnd datetime = '2020-09-04 00:00:00.000';
declare @TimeStep nvarchar(64) = '10'
Declare @List Varchar(1000) = N'SysInfo\CPU_1;SysInfo\CPU_2;SysInfo\CPU_3;SysInfo\CPU_4'
declare @strTimeBegin nvarchar(64) = format(Dateadd(hh, DATEDIFF(hh,GETDATE(),GETUTCDATE()), @TimeBegin),'yyyy-MM-dd HH:mm:ss.fff')
declare @strTimeEnd nvarchar(64) = format(Dateadd(hh, DATEDIFF(hh,GETDATE(),GETUTCDATE()), @TimeEnd),'yyyy-MM-dd HH:mm:ss.fff')
declare @strTimeStep nvarchar(500)
if @TimeStep<>''
set @strTimeStep = N', ''''TimeStep=' + @TimeStep +',1'''' '
else
set @strTimeStep = ''
declare @temp table
(
ValueID bigint,
TimeStamp datetime,
RealValue float,
Quality int,
Flags int
)
declare @SQL nvarchar(1000)
set @SQL = 'select * from openquery(LnkRtDb_WinCCOLEDB,''Tag:R,('+@List+'), '''''+@strTimeBegin+''''' ,'''''+@strTimeEnd+''''' ' +@strTimeStep+ ' '')'
insert into @temp exec(@SQL)
SELECT Dateadd(hh, DATEDIFF(hh,GETUTCDATE(),GETDATE()), [TimeStamp]) AS TimeStamp, [1] AS CPU_1, [2] AS CPU_2, [3] AS CPU_3, [4] AS CPU_4
From
(SELECT [ValueID], [TimeStamp], [RealValue] from @temp ) AS SourceTable
PIVOT (max(Realvalue) for ValueID in ([1],[2],[3],[4])) AS PivotTable
order by PivotTable.TimeStamp
用VB腳本訪問歸檔數據庫
創建數據庫連接
dim conn
Set conn = CreateObject("ADODB.Connection")
conn.ConnectionString = "Provider=WinCCOLEDBProvider.1;Catalog=CC_OpenArch_03_05_27_14_11_46R; Data Source=.\WinCC"
conn.CursorLocation = 3
conn.open
查詢數據庫
Dim rs, Sql
Set rs = CreateObject("ADODB.Recordset")
Sql = "Tag:R,1,''0000-00-00 00:10:00.000'',''0000-00-00 00:00:00.000''"
rs.Open Sql, conn, 1, 3
訪問另一台電腦的WinCC歸檔數據庫
假如有兩台電腦,命名為A和B,A和B電腦上都安裝了ConnectivityPack,從A電腦上通過WinCCOleDbProvider.1去訪問B電腦中的WinCC歸檔數據庫,需要按照如下做法:
- B電腦的SQL Server數據庫中要給A電腦的Windows賬戶添加訪問權限。因為WinCCOleDbProvider.1訪問需要通過Windows賬戶認證,沒有從資料中查到如何使用SQL Server賬戶認證。
- Data Source使用B電腦的數據庫地址,Catalog使用B電腦WinCC數據庫名。
下圖使用openDatasource訪問方法進行測試,本地電腦A為WIN-OJHUAJ0TT67,遠程電腦B為192.168.248.128:

查詢WinCC過程值歸檔的語法詳解:查看文檔
過程值字段類型:查看文檔
查詢WinCC報警消息歸檔的語法詳解:查看文檔
報警消息歸檔字段類型:查看文檔
