How to fix 25007: schema_and_data_statement_mixing_not_supported in PostgreSQL

PostgreSQLINTERMEDIATEMEDIUMUpdated Dec 22, 2025· 88 views

The PostgreSQL error "25007: schema_and_data_statement_mixing_not_supported" occurs when attempting to mix schema modification statements (DDL) with data manipulation statements (DML) in contexts where they cannot be combined. This typically happens in prepared statements, certain transaction blocks, or when using specific PostgreSQL extensions that have restrictions on statement mixing.

Quick fix

Fixes 25007: schema_and_data_statement_mixing_not_supported

-- This will cause 25007 error in prepared statements:
PREPARE myplan AS 
  CREATE TABLE temp_users (id SERIAL, name TEXT);
  INSERT INTO temp_users (name) VALUES ('test');

-- Instead, use separate statements:
PREPARE create_table AS CREATE TABLE temp_users (id SERIAL, name TEXT);
PREPARE insert_data AS INSERT INTO temp_users (name) VALUES ($1);

-- Execute separately:
EXECUTE create_table;
EXECUTE insert_data('test');
  1. Separate schema and data operations into distinct statements
  2. Use explicit transaction blocks with proper statement ordering
  3. Avoid mixing in PL/pgSQL dynamic SQL execution
  4. Review and modify prepared statement usage
postgresql — error
-- This will cause 25007 error in prepared statements:
PREPARE myplan AS
CREATE TABLE temp_users (id SERIAL, name TEXT);
INSERT INTO temp_users (name) VALUES ('test');
-- Instead, use separate statements:
PREPARE create_table AS CREATE TABLE temp_users (id SERIAL, name TEXT);
PREPARE insert_data AS INSERT INTO temp_users (name) VALUES ($1);
-- Execute separately:
EXECUTE create_table;
EXECUTE insert_data('test');
25007: schema_and_data_statement_mixing_not_supported

What this error means

The "schema_and_data_statement_mixing_not_supported" error (SQLSTATE 25007) is a PostgreSQL error that prevents mixing Data Definition Language (DDL) statements with Data Manipulation Language (DML) statements in certain execution contexts. DDL statements include operations that modify the database schema, such as: - CREATE TABLE, ALTER TABLE, DROP TABLE - CREATE INDEX, DROP INDEX - CREATE VIEW, ALTER VIEW - GRANT, REVOKE permissions DML statements include operations that manipulate data within existing tables: - SELECT, INSERT, UPDATE, DELETE - COPY, TRUNCATE (though TRUNCATE has DDL characteristics) PostgreSQL restricts mixing these statement types in: 1. Prepared statements that will be executed multiple times 2. Certain PL/pgSQL function contexts 3. Cursors and some query execution plans 4. Specific replication or logical decoding scenarios This restriction exists because schema changes can invalidate execution plans and prepared statement parameter types, leading to runtime errors or data corruption.

Typical symptoms

  • PostgreSQL returns error "25007: schema_and_data_statement_mixing_not_supported"
  • Prepared statements fail when they contain both CREATE/ALTER and SELECT/INSERT statements
  • Batch scripts or migration files fail when mixing schema and data operations
  • PL/pgSQL functions or procedures fail when combining DDL and DML in single execution contexts
  • Error occurs specifically in prepared statement execution or certain transaction blocks
  • Database drivers or ORMs report mixing not supported errors

Common causes

  1. Creating prepared statements that mix DDL (CREATE/ALTER) with DML (SELECT/INSERT/UPDATE/DELETE)
  2. Using EXECUTE in PL/pgSQL with dynamic SQL that combines schema and data operations
  3. Attempting to combine schema changes and data modifications in single SQL command strings
  4. Certain PostgreSQL extensions or features that have restrictions on statement mixing
  5. Application code that builds SQL dynamically without separating schema and data operations
  6. Migration tools that generate combined DDL/DML statements in single transactions
  7. Using COPY with schema creation in same prepared statement context

How to fix "25007: schema_and_data_statement_mixing_not_supported"

1Separate schema and data operations into distinct statements

The most straightforward fix is to separate DDL (schema) and DML (data) operations into separate statements or execution contexts:

sql
-- This will cause 25007 error in prepared statements:
PREPARE myplan AS 
  CREATE TABLE temp_users (id SERIAL, name TEXT);
  INSERT INTO temp_users (name) VALUES ('test');

-- Instead, use separate statements:
PREPARE create_table AS CREATE TABLE temp_users (id SERIAL, name TEXT);
PREPARE insert_data AS INSERT INTO temp_users (name) VALUES ($1);

-- Execute separately:
EXECUTE create_table;
EXECUTE insert_data('test');

Always separate CREATE/ALTER/DROP statements from SELECT/INSERT/UPDATE/DELETE statements.

2Use explicit transaction blocks with proper statement ordering

When you need both schema and data operations in a transaction, ensure they are in separate statements within the transaction block:

sql
BEGIN;

-- Schema operation (DDL)
CREATE TABLE audit_log (
  id SERIAL PRIMARY KEY,
  event_time TIMESTAMP,
  message TEXT
);

-- Data operation (DML)
INSERT INTO audit_log (event_time, message) 
VALUES (NOW(), 'Table created');

COMMIT;

Note: Even in transactions, some contexts (like prepared statements) still restrict mixing. The key is having them as separate SQL statements, not combined in a single command string.

3Avoid mixing in PL/pgSQL dynamic SQL execution

PL/pgSQL's EXECUTE command can have restrictions on statement mixing. Separate schema and data operations:

sql
CREATE OR REPLACE FUNCTION setup_audit() RETURNS void AS $$
BEGIN
  -- Schema operation
  EXECUTE 'CREATE TABLE IF NOT EXISTS audit_trail (id SERIAL, data JSONB)';
  
  -- Data operation (separate EXECUTE)
  EXECUTE 'INSERT INTO audit_trail (data) VALUES ('"setup complete"'::jsonb)';
END;
$$ LANGUAGE plpgsql;

Do not combine CREATE and INSERT in a single EXECUTE string, as this can trigger the 25007 error.

4Review and modify prepared statement usage

Prepared statements are optimized for repeated execution with different parameters. Schema changes break this model. Check your application code:

javascript
// Problematic - mixing DDL and DML in prepared statement
const badStatement = await pool.query(
  `CREATE TEMP TABLE temp_data (id INT); INSERT INTO temp_data VALUES ($1)`,
  [123]
);

// Correct - separate statements
await pool.query('CREATE TEMP TABLE temp_data (id INT)');
await pool.query('INSERT INTO temp_data VALUES ($1)', [123]);

Most database drivers and ORMs will handle this automatically if you use separate method calls for different statement types.

5Check for COPY command restrictions

The COPY command has specific restrictions when used with schema operations. COPY is considered a DML operation for this purpose:

sql
-- This may cause 25007 in some contexts:
CREATE TABLE imported_data (col1 TEXT, col2 INT);
COPY imported_data FROM '/path/to/data.csv' CSV HEADER;

-- Ensure they are separate execution contexts or statements
-- First create table, then separately execute COPY

If using COPY within a function or prepared context, ensure no schema operations are mixed in the same execution unit.

6Examine migration scripts and batch operations

Migration tools and batch scripts often combine operations. Review your migration files:

sql
-- Problematic migration:
-- 001_create_and_populate.sql
CREATE TABLE settings (key TEXT PRIMARY KEY, value TEXT);
INSERT INTO settings VALUES ('version', '1.0');

-- Better approach:
-- 001_create_table.sql
CREATE TABLE settings (key TEXT PRIMARY KEY, value TEXT);

-- 002_initial_data.sql  
INSERT INTO settings VALUES ('version', '1.0');

Separate schema creation and data population into different migration files or distinct parts of your deployment process.

Advanced notes

The 25007 error code is part of PostgreSQL's "Class 25 — Invalid Transaction State" error category. This specific error "schema_and_data_statement_mixing_not_supported" protects against several potential issues:

Execution Plan Invalidation: When a prepared statement includes DDL, subsequent executions could have different table structures, column types, or indexes, making cached execution plans invalid.

Parameter Type Resolution: Prepared statements resolve parameter types based on the statement context. DDL operations can change these types between executions.

Transaction Consistency: Some schema changes require exclusive locks or have different transactional semantics than DML operations.

Historical Context: This restriction has become more prominent with increased use of prepared statements for security (preventing SQL injection) and performance. Earlier PostgreSQL versions were more permissive but could produce subtle bugs.

Extension-Specific Behavior: Certain PostgreSQL extensions (like PostGIS, TimescaleDB) may have their own restrictions on statement mixing. Always check extension documentation.

Performance Considerations: While separating statements adds round-trips, it ensures correct execution. For bulk operations, consider using COPY for data loading after separate table creation.

Debugging Tips:
1. Use EXPLAIN to see how PostgreSQL parses and plans your statements
2. Check pg_prepared_statements view to see existing prepared statements
3. Review PostgreSQL logs for the full error context and stack traces
4. Test statements interactively with psql before embedding in application code

Related Errors:
- 25006: read_only_sql_transaction - When attempting writes in read-only mode
- 25001: active_sql_transaction - Transaction already in progress issues
- 26000: invalid_sql_statement_name - Problems with prepared statement names
- 0A000: feature_not_supported - General "not supported" error for various operations

Frequently asked questions

What does "25007: schema_and_data_statement_mixing_not_supported" mean?
The "schema_and_data_statement_mixing_not_supported" error (SQLSTATE 25007) is a PostgreSQL error that prevents mixing Data Definition Language (DDL) statements with Data Manipulation Language (DML) statements in certain execution contexts. DDL statements include operations that modify the database schema, such as: - CREATE TABLE, ALTER TABLE, DROP TABLE - CREATE INDEX, DROP INDEX - CREATE VIEW, ALTER VIEW - GRANT, REVOKE permissions DML statements include operations that manipulate data within existing tables: - SELECT, INSERT, UPDATE, DELETE - COPY, TRUNCATE (though TRUNCATE has DDL characteristics) PostgreSQL restricts mixing these statement types in: 1. Prepared statements that will be executed multiple times 2.
How do I fix "25007: schema_and_data_statement_mixing_not_supported"?
The PostgreSQL error "25007: schema_and_data_statement_mixing_not_supported" occurs when attempting to mix schema modification statements (DDL) with data manipulation statements (DML) in contexts where they cannot be combined. This typically happens in prepared statements, certain transaction blocks, or when using specific PostgreSQL extensions that have restrictions on statement mixing.
What causes "25007: schema_and_data_statement_mixing_not_supported"?
Creating prepared statements that mix DDL (CREATE/ALTER) with DML (SELECT/INSERT/UPDATE/DELETE) Using EXECUTE in PL/pgSQL with dynamic SQL that combines schema and data operations Attempting to combine schema changes and data modifications in single SQL command strings
Is the "25007: schema_and_data_statement_mixing_not_supported" error serious?
It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.

Official resources & further reading