Files
scadaproj/aveva-historian-sql-reference.md
T

7.8 KiB
Raw Blame History

AVEVA Historian — SQL Reference: Tag Value Recording & Tag Registration

Scope: Writing tag values and creating new tags in AVEVA Historian (formerly Wonderware Historian) directly through SQL Server, against the INSQL OLE DB provider / Runtime database. Applies to 2020 and 2023 R2 (history-block / binary storage).

Connection model: Connect to the Historian's SQL Server instance (e.g. Microsoft.Data.SqlClient). The time-series tables are extension tables — they don't physically exist in SQL Server; the INSQL provider routes reads/writes into the on-disk history blocks. No Framework SDK / HCAL required for this path.

Out of scope: Alarm/event recording. In high-speed mode the alarm/event store is fed only by the Application Server alarm provider — there is no supported SQL INSERT for alarms/events. Model process outcomes (pass/fail/cancel) as the tags below, or raise real alarms via an AppServer attribute. See the "Alarms/events" note at the end.


1. Recording tag VALUES via SQL

Two different tables depending on tag type. This is the most common trap.

1a. Analog & discrete tags → History table (numeric Value)

INSERT INSQL.Runtime.dbo.History (DateTime, TagName, Value, QualityDetail, wwVersion)
VALUES ('2026-06-18 10:00:00.000', 'LeakTest_Rate', 0.42, 0, 'Latest');
  • Value is a float (analog real value, or 0/1 for discrete).
  • Four-part naming: INSQL.Runtime.dbo.History.

1b. String tags → StringHistory table (string Value)

INSERT INSQL.Runtime.dbo.StringHistory (DateTime, TagName, Value, QualityDetail, wwVersion)
VALUES ('2026-06-18 10:00:00.000', 'LeakTest_Result', 'PASS', 0, 'Latest');
  • Use StringHistory + Value, not History + vValue for strings.
  • Inserting a string into History.vValue fails on 2023 R2 with Msg 8114 ... Error converting data type nvarchar to (null).

Column notes

Column Meaning
DateTime Timestamp of the value (local server time unless using a UTC column).
TagName Must already exist (see Section 2 to create it).
Value Float in History; string in StringHistory.
QualityDetail 0 = good. (OPC-style alternative: OPCQuality, where 192 = good. Confirm which your queries expect.)
wwVersion 'Latest' or 'Original' — see below.

wwVersion / data versioning

  • 'Latest' — writes a revision that wins on retrieval.
  • 'Original' — as-acquired value; never destroyed, still readable with wwVersion = 'Original'.
  • An "update" is really a new revision layered on top, not an overwrite.
  • UPDATE of existing points generally must go through OPENQUERY:
    SELECT * FROM OPENQUERY(INSQL,
      'update History set Value = 40
         where TagName = ''LeakTest_Rate''
           and DateTime = ''2026-06-18 10:00:00.000''');
    

Constraints / gotchas

  • Real-time window: values are accepted roughly -30 s to +999 ms around Historian time; outside that, a value sent as real-time/streamed may be discarded. Sync clocks for current-time inserts.
  • Back-dating originals: to insert original (non-streamed) data into the past, the system parameter AllowOriginals must permit it; otherwise you can only write revisions. Late/back-filled inserts trigger summary recomputation.
  • Tag must accept manual data — feed values into a manually-acquired / MDAS-style tag (or a tag configured so the Historian isn't expecting IDAS data). Tag ownership governs acceptance.
  • Value semantics differ from a relational row: a stored value represents a change that persists until superseded by a later timestamp (step/sample-and-hold), not a discrete row. Timestamp rounding can make an insert look like a duplicate of the original point.

2. Registering (creating) NEW tags via SQL

Tag definitions live in normal SQL config tables in the Runtime database (not extension tables). Insert the definition, then commit to activate it.

Config tables (insert target by type)

Tag type Config table Database Reference pg.
Analog AnalogTag ~294
Discrete DiscreteTag ~296
String StringTag ~299

Dependency order (create these first if they don't exist)

IDAS → IOServer → Topic → (EngineeringUnits for analog / MessagePairs for discrete) → tag

The export/import scanner makes no attempt to resolve ordering, so parents must precede children. For SQL/SDK-fed (manual) tags, set the acquisition type so the Historian does not expect IDAS data — these tags receive values only from your INSERTs (Section 1).

Method

  1. INSERT the row(s) into AnalogTag / DiscreteTag / StringTag with the required columns (TagName, storage/acquisition keys, type-specific fields such as MinEU/MaxEU/EngUnit for analog or message pair for discrete).
  2. Activate the pending config:
    EXEC aaCommitChanges;
    
    This is the T-SQL equivalent of "Commit Pending Changes" in the System Management Console; config changes on a running Historian don't take effect until committed. (aaCommitChangesAtStartup is the deferred-at-restart variant.)

Exact column lists vary and are column-heavy (storage node, acquisition type, storage type/rate, scaling, raw type, etc.). Confirm against the AVEVA Historian Database Reference, AnalogTag/DiscreteTag/StringTag sections (pp. ~294299) for your version before scripting.

Alternatives to raw config-table INSERT

  • CSV import — the Database Configuration Export/Import utility (sectioned text file: :(IOServer), :(Topic), :(AnalogTag), :(DiscreteTag), :(StringTag), …). Best for bulk tag creation; copy an existing tag's exported row, change the name/params.
  • Historian SDK — programmatic tag creation (.NET Framework; pulls HCAL back in).
  • SMC GUI — manual, one tag at a time (right-click Topic → New Analog/Discrete/String Tag → Commit Pending Changes).

3. Quick template (manual tag → values), end to end

-- 1) Define a manual analog result tag (illustrative columns — verify vs Database Reference)
INSERT INSQL.Runtime.dbo.AnalogTag (TagName, /* storage/acquisition + EU columns */ ...)
VALUES ('LeakTest_Rate', /* ... */);

-- 2) Activate it
EXEC aaCommitChanges;

-- 3) Write values
INSERT INSQL.Runtime.dbo.History (DateTime, TagName, Value, QualityDetail, wwVersion)
VALUES (SYSDATETIME(), 'LeakTest_Rate', 0.42, 0, 'Latest');

For a string outcome tag, swap AnalogTagStringTag and History/Value(float)StringHistory/Value(string).


Alarms / events (why they're not here)

Alarms and events cannot be SQL-inserted into the high-speed (history-block) store — it is populated exclusively by an Application Engine configured as Alarm Provider (with storage-to-Historian enabled). The v_AlarmHistory / v_AlarmHistory2 / v_AlarmEventHistory2 views are read-only retrieval surfaces.

  • Want a real alarm/event (live + historical, visible in alarm clients): raise it from an AppServer attribute alarm or the LogDataChangeEvent event primitive — not SQL.
  • Want a historical-only event record in dbo.Events: the documented writer is the Historian SDK; those records are never raised in the live A&E system. A direct INSERT into dbo.Events is undocumented/unsupported and unverified for high-speed persistence — avoid for production.
  • Recommended: record process outcomes as the tags in Sections 12, and (if an event-style query surface is needed) put a SQL view over the result tags.

Reference compiled from AVEVA Historian documentation (Database Reference, Administration Guide, Retrieval Guide, Concepts Guide) and AVEVA community guidance. Verify exact table columns and system-parameter behavior against the Database Reference for your specific version (2020 / 2023 R2) before production use.