Skip to content

TInsertSqlStatement

Overview

The TInsertSqlStatement node represents INSERT statements in SQL. It handles various forms of data insertion including VALUES clauses, subqueries, and database-specific extensions.

SQL to AST Mapping

Simple INSERT with VALUES

1
2
INSERT INTO Production.UnitMeasure (Name, UnitMeasureCode, ModifiedDate)
VALUES (N'Square Yards', N'Y2', GETDATE());

AST Structure:

1
2
3
4
5
6
7
8
9
TInsertSqlStatement
├── targetTable: TTable (Production.UnitMeasure)
├── columnList: TObjectNameList (Name, UnitMeasureCode, ModifiedDate)
├── insertSource: EInsertSource.values
└── values: TMultiTargetList
    └── TMultiTarget
        ├── TExpression (N'Square Yards')
        ├── TExpression (N'Y2')
        └── TExpression (GETDATE())

INSERT with Subquery

1
2
3
4
5
INSERT INTO dbo.EmployeeSales
SELECT 'SELECT', sp.BusinessEntityID, c.LastName, sp.SalesYTD
FROM Sales.SalesPerson AS sp
INNER JOIN Person.Person AS c ON sp.BusinessEntityID = c.BusinessEntityID
WHERE sp.BusinessEntityID LIKE '2%';

AST Structure:

1
2
3
4
5
6
7
TInsertSqlStatement
├── targetTable: TTable (dbo.EmployeeSales)
├── insertSource: EInsertSource.subquery
└── subQuery: TSelectSqlStatement
    ├── resultColumnList: TResultColumnList
    ├── fromClause: TFromClause
    └── whereClause: TWhereClause

Multi-row INSERT

1
2
3
4
INSERT INTO users (name, email, age) VALUES 
('John Doe', 'john@example.com', 30),
('Jane Smith', 'jane@example.com', 25),
('Bob Johnson', 'bob@example.com', 35);

AST Structure:

1
2
3
4
5
6
7
8
TInsertSqlStatement
├── targetTable: TTable (users)
├── columnList: TObjectNameList (name, email, age)
├── insertSource: EInsertSource.values
└── values: TMultiTargetList
    ├── TMultiTarget (John Doe, john@example.com, 30)
    ├── TMultiTarget (Jane Smith, jane@example.com, 25)
    └── TMultiTarget (Bob Johnson, bob@example.com, 35)

Key Properties

Property Type Description Access Method
targetTable TTable Target table for insertion getTargetTable()
columnList TObjectNameList Column names (optional) getColumnList()
insertSource EInsertSource Type of data source getInsertSource()
values TMultiTargetList VALUES clause data getValues()
subQuery TSelectSqlStatement Subquery data source getSubQuery()
insertToken TSourceToken INSERT keyword getInsertToken()

Insert Source Types

The EInsertSource enum determines the type of data source:

Source Type Description Access Method
values VALUES clause getValues()
subquery SELECT statement getSubQuery()
values_empty Empty VALUES () N/A
default_values DEFAULT VALUES N/A
execute EXECUTE statement (SQL Server) getExecuteStmt()
values_function Function call getFunctionCall()

Common Usage Patterns

Analyzing Insert Data Sources

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public void analyzeInsertStatement(TInsertSqlStatement insert) {
    System.out.println("Target table: " + insert.getTargetTable().getFullName());

    // Check column list
    if (insert.getColumnList() != null) {
        System.out.println("Columns specified:");
        for (int i = 0; i < insert.getColumnList().size(); i++) {
            System.out.println("  " + insert.getColumnList().getObjectName(i));
        }
    }

    // Analyze data source
    switch (insert.getInsertSource()) {
        case values:
            analyzeValuesClause(insert.getValues());
            break;
        case subquery:
            analyzeSubquery(insert.getSubQuery());
            break;
        case default_values:
            System.out.println("Using DEFAULT VALUES");
            break;
        default:
            System.out.println("Other insert source: " + insert.getInsertSource());
    }
}

Processing VALUES Clauses

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
public void analyzeValuesClause(TMultiTargetList values) {
    if (values == null) return;

    System.out.println("Number of value rows: " + values.size());

    for (int i = 0; i < values.size(); i++) {
        TMultiTarget row = values.getMultiTarget(i);
        System.out.println("Row " + (i + 1) + ":");

        if (row.getColumnList() != null) {
            for (int j = 0; j < row.getColumnList().size(); j++) {
                TResultColumn col = row.getColumnList().getResultColumn(j);
                TExpression expr = col.getExpr();
                System.out.println("  Value " + (j + 1) + ": " + expr.toString());
            }
        }
    }
}

Extracting Referenced Tables

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
public Set<String> getReferencedTables(TInsertSqlStatement insert) {
    Set<String> tables = new HashSet<>();

    // Target table
    tables.add(insert.getTargetTable().getFullName());

    // Tables from subquery
    if (insert.getInsertSource() == EInsertSource.subquery && 
        insert.getSubQuery() != null) {

        insert.getSubQuery().acceptChildren(new TParseTreeVisitor() {
            public void preVisit(TParseTreeNode node) {
                if (node instanceof TTable) {
                    TTable table = (TTable) node;
                    tables.add(table.getFullName());
                }
            }
        });
    }

    return tables;
}

Column-Value Validation

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public List<String> validateColumnValueMatch(TInsertSqlStatement insert) {
    List<String> errors = new ArrayList<>();

    if (insert.getColumnList() == null || insert.getValues() == null) {
        return errors; // No validation needed
    }

    int expectedColumns = insert.getColumnList().size();

    for (int i = 0; i < insert.getValues().size(); i++) {
        TMultiTarget row = insert.getValues().getMultiTarget(i);
        if (row.getColumnList() != null) {
            int actualValues = row.getColumnList().size();
            if (actualValues != expectedColumns) {
                errors.add(String.format(
                    "Row %d: Expected %d values, got %d", 
                    i + 1, expectedColumns, actualValues));
            }
        }
    }

    return errors;
}

Database-Specific Features

SQL Server

1
2
3
4
5
6
7
8
-- OUTPUT clause
INSERT INTO target_table (col1, col2)
OUTPUT INSERTED.id, INSERTED.col1
VALUES (1, 'value');

-- TOP clause
INSERT TOP (10) INTO target_table
SELECT * FROM source_table;

Access via: - getOutputClause() - OUTPUT clause - getTopClause() - TOP clause

MySQL

1
2
3
4
5
6
7
8
-- ON DUPLICATE KEY UPDATE
INSERT INTO users (id, name, email) 
VALUES (1, 'John', 'john@example.com')
ON DUPLICATE KEY UPDATE name = VALUES(name);

-- IGNORE keyword
INSERT IGNORE INTO users (name, email) 
VALUES ('John', 'john@example.com');

Access via: - getOnDuplicateKeyUpdate() - ON DUPLICATE KEY UPDATE clause - getIgnore() - IGNORE keyword - getPriority_delayed() - Priority keywords

Oracle

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
-- INSERT ALL
INSERT ALL
  INTO sales (prod_id, cust_id, time_id, amount)
  VALUES (product_id, customer_id, weekly_start_date, sales_sun)
  INTO sales (prod_id, cust_id, time_id, amount)
  VALUES (product_id, customer_id, weekly_start_date+1, sales_mon)
SELECT * FROM sales_input_table;

-- Error logging
INSERT INTO target_table
SELECT * FROM source_table
LOG ERRORS INTO error_table;

Access via: - isInsertAll() - INSERT ALL - isInsertFirst() - INSERT FIRST - getErrorLoggingClause() - Error logging

PostgreSQL

1
2
3
4
-- RETURNING clause
INSERT INTO users (name, email) 
VALUES ('John', 'john@example.com')
RETURNING id, created_at;

Access via: - getReturningClause() - RETURNING clause

Performance Considerations

Batch Insert Analysis

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
public void analyzeBatchInsert(TInsertSqlStatement insert) {
    if (insert.getInsertSource() == EInsertSource.values && 
        insert.getValues() != null) {

        int rowCount = insert.getValues().size();
        if (rowCount > 1000) {
            System.out.println("Warning: Large batch insert (" + rowCount + " rows)");
            System.out.println("Consider using bulk insert methods");
        }
    }
}

Index Impact Assessment

1
2
3
4
5
public void assessIndexImpact(TInsertSqlStatement insert) {
    // Analyze which columns are being inserted
    // Check for potential index maintenance overhead
    // Suggest optimization strategies
}

See Also