diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql.Dialect/ISqlDialect.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql.Dialect/ISqlDialect.cs
index 80fea8d4..2dd04716 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql.Dialect/ISqlDialect.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql.Dialect/ISqlDialect.cs
@@ -56,10 +56,10 @@ public interface ISqlDialect
///
/// The token that stands for a bound parameter in the command text — "@k0" for
- /// SqlClient/Npgsql, ":k0" for ODP.NET — given the caller's bare base name ("k0",
+ /// SqlClient/Npgsql, ":p_k0" for ODP.NET — given the caller's bare base name ("k0",
/// "w", "schema").
/// Why the marker and the bind name are two members. They are the same string on every
- /// provider but Oracle, where the SQL text carries :schema while
+ /// provider but Oracle, where the SQL text carries :p_schema while
/// is the bare schema. Modelling one and deriving the
/// other means a call site guessing at a convention it does not own — the exact defect this seam
/// exists to prevent, and one that surfaces as a runtime bind failure (or, worse under
@@ -91,7 +91,7 @@ public interface ISqlDialect
/// parameters are added or it is executed. A no-op for providers that need none.
/// Oracle uses this to set OracleCommand.BindByName = true, and that call is the
/// sharpest correctness edge on this seam: ODP.NET binds by position by default, so a
- /// multi-parameter statement (the planner's IN (:k0, :k1, …) list, the catalog path's
+ /// multi-parameter statement (the planner's IN (:p_k0, :p_k1, …) list, the catalog path's
/// schema + table pair) would bind values to the wrong markers whenever the parameter
/// order and the marker order differ — publishing one tag's value onto another tag's node with no
/// error anywhere. Every command that carries parameters — the poll path, the catalog path, the
@@ -164,7 +164,7 @@ public interface ISqlDialect
///
/// Catalog query listing tables + views in one schema — the browser's schema-expand level. Carries one
/// parameter under the base name schema, spelled with this dialect's own
- /// (@schema on SqlClient, :schema on ODP.NET); callers bind
+ /// (@schema on SqlClient, :p_schema on ODP.NET); callers bind
/// it under of the same base name.
///
string ListTablesSql { get; }
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql/SqlCatalogLoader.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql/SqlCatalogLoader.cs
index 289163c2..7635112c 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql/SqlCatalogLoader.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql/SqlCatalogLoader.cs
@@ -18,7 +18,7 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.Sql;
/// the allow-list cannot itself be an injection vector. No identifier is quoted into text on this path.
/// The bind names come from over those two base names, so
/// they can never disagree with the markers in the dialect's own catalog SQL (@schema on SQL
-/// Server, :schema on Oracle).
+/// Server, :p_schema on Oracle).
/// Failures throw; they do not degrade to an empty catalog. An empty catalog would reject
/// every tag, which is indistinguishable at the OPC UA surface from a database whose objects were all
/// dropped. A caller that cannot read the catalog has not learned that the tags are invalid — it has
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql/SqlGroupPlanner.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql/SqlGroupPlanner.cs
index a6aa0854..1dfc08bf 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql/SqlGroupPlanner.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql/SqlGroupPlanner.cs
@@ -14,13 +14,13 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.Sql;
/// Injection boundary (design §8.1). Identifiers reach the command text through
/// and nothing else; every authored value becomes a
/// k0/w parameter — spelled with the dialect's own
-/// (@k0 on SQL Server, :k0 on Oracle) — with the value carried in
+/// (@k0 on SQL Server, :p_k0 on Oracle) — with the value carried in
/// . There is no interpolation of tag content into SQL anywhere in
/// this type.
/// The base names are this planner's, the spelling is the dialect's. Each plan carries the
/// markers it emitted and the matching s, so the
/// reader binds what the planner minted instead of re-deriving a provider convention — the two differ on
-/// ODP.NET (:k0 in the text, bare k0 on the parameter).
+/// ODP.NET (:p_k0 in the text, bare p_k0 on the parameter).
///
public static class SqlGroupPlanner
{
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql/SqlQueryPlan.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql/SqlQueryPlan.cs
index 0ba78717..d9c14dbe 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql/SqlQueryPlan.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Sql/SqlQueryPlan.cs
@@ -12,8 +12,8 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.Sql;
/// named by the positionally-aligned . There is
/// no path by which a tag's keyValue or whereValue reaches the command text.
/// Markers and bind names are carried separately because they are not the same string on
-/// every provider: ODP.NET's text says :k0 while its is the
-/// bare k0. Both lists are positionally aligned with , so a binding site
+/// every provider: ODP.NET's text says :p_k0 while its is the
+/// bare p_k0. Both lists are positionally aligned with , so a binding site
/// copies the pairing the planner minted rather than re-deriving a provider convention it does not own.
/// Produced only by ; consumed by the poll reader, which executes
/// once and slices the rows back to per-member snapshots.