Hey @austinoyoung ,
Short answer: Donโt try to pull the sequence in your Spark insert. Let Oracle assign it.
Why this happens (ORA-02287: sequence number not allowed here๐
Sparkโs JDBC writer generates parameterized INSERT statements like:
INSERT INTO your_table (id, col_a, col_b) VALUES (?, ?, ?)
The ? parameters must be literal values. Oracle sequences (e.g., myseq.nextval) are expressions and cannot be used in that context. Thatโs why Oracle rejects the insert.
Recommended approaches (no pure Python loops)
-
Identity column (Oracle 12c+)
If you can alter the table, make the key auto-generated by Oracle:
ALTER TABLE your_table
MODIFY (id NUMBER GENERATED BY DEFAULT AS IDENTITY);
Then drop the id column before writing from Spark:
df.drop("id").write \
.format("jdbc") \
.option("url", jdbcUrl) \
.option("dbtable", "your_table") \
.option("user", user) \
.option("password", pwd) \
.mode("append") \
.save()
-
Default value backed by a sequence (also Oracle 12c+)
Keep your sequence but make the column default to it:
ALTER TABLE your_table
MODIFY (id NUMBER DEFAULT your_seq.NEXTVAL);
Then, again, donโt send id from Spark.
-
BEFORE INSERT trigger (works on older Oracle versions)
If identity/default isnโt allowed:
CREATE OR REPLACE TRIGGER your_table_bi
BEFORE INSERT ON your_table
FOR EACH ROW
WHEN (NEW.id IS NULL)
BEGIN
:NEW.id := your_seq.NEXTVAL;
END;
/
Omit id in your DataFrame and Oracle will set it automatically.
Why not generate IDs in Spark?
Functions like monotonically_increasing_id() or UUIDs wonโt increment the Oracle sequence, and can cause gaps or ordering issues if other systems rely on Oracleโs sequence.
Summary
- Donโt try to select the sequence in your Spark insert.
- Let Oracle handle the ID via identity, default+sequence, or a trigger.
- Just drop the id column from your DataFrame before writing.
Hope this helps, Louis.