Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create trigger Oracle Missing IN or OUT #228

Closed
blindcoding9 opened this issue Sep 29, 2022 · 4 comments
Closed

Create trigger Oracle Missing IN or OUT #228

blindcoding9 opened this issue Sep 29, 2022 · 4 comments
Assignees
Labels
documentation The documentation is wrong or needs improving

Comments

@blindcoding9
Copy link

When I try execute a stmt Im facing SQLException Missing IN or OUT parameter at index:: 1

(jdbc/execute! @datasource ["CREATE TABLE T_TEMP AS SELECT sysdate AS d FROM dual"])
=> [#:next.jdbc{:update-count 1}]

(jdbc/execute! @datasource ["CREATE SEQUENCE SEQ_TEMP"])
=> [#:next.jdbc{:update-count 0}]

(jdbc/execute! @datasource ["CREATE OR REPLACE EDITIONABLE TRIGGER T_TEMP_TRIGGER
BEFORE INSERT ON T_TEMP
REFERENCING NEW AS NEW OLD AS OLD FOR EACH ROW
DECLARE
BEGIN
	IF inserting THEN
		IF :new.id IS NULL THEN
			SELECT SEQ_TEMP.nextval
			  INTO :new.id
			  FROM dual;
		END IF;
	END IF;
END;"])
Execution error (SQLException) at oracle.jdbc.driver.OraclePreparedStatement/processCompletedBindRow (OraclePreparedStatement.java:2017).
Missing IN or OUT parameter at index:: 1 
@seancorfield
Copy link
Owner

I don't use Oracle and don't have access to it to test anything -- the error is coming from the underlying JDBC driver (not next.jdbc) and I would expect such an error to occur on the call to a proc, not the definition.

One thing you might try is to remove the ; at the end of the statement in case Oracle's driver thinks that's an additional statement and/or some kind of proc invocation.

Other than that, I have no idea (and I cannot provide support for Oracle-related issues -- you'll need to ask someone who uses Oracle, perhaps in the #sql channel on the Clojurians Slack -- you can sign up at http://clojurians.net ).

@blindcoding9
Copy link
Author

blindcoding9 commented Sep 30, 2022

I found the solution

When using a 10g (or higher) Oracle JDBC driver, attempts to create a trigger fail when the syntax for doing so contains :OLD (or :NEW) types of references. The following exception is thrown:

Missing IN or OUT parameter at index:: 1

CAUSE

This is expected behavior when using a PreparedStatement or a CallableStatement.

Beginning in the 10g drivers, a feature was added that allows binding parameters by name.

As a consequence of this, strings such as ":old" are interpreted by the JDBC driver as bind variables.

Both PreparedStatement and CallableStatement check in advance that values have been provided for all bind variables.

With no value provided for ":old", since it's not intended in this context to be a bind variable, the error is thrown.

Solution

Use Statement rather than PreparedStatement or CallableStatement.

(with-open [con (jdbc/get-connection @datasource)]
    (let [stmt (prepare/statement con)]
      (.executeUpdate stmt (str "CREATE OR REPLACE EDITIONABLE TRIGGER T_TEMP_TRIGGER
BEFORE INSERT ON T_TEMP
REFERENCING NEW AS NEW OLD AS OLD FOR EACH ROW
DECLARE
BEGIN
	IF inserting THEN
		IF :new.id IS NULL THEN
			SELECT SEQ_TEMP.nextval
			  INTO :new.id
			  FROM dual;
		END IF;
	END IF;
END;
/"))))
=> 0

@seancorfield
Copy link
Owner

I'll reopen this and add a Tips & Tricks note about it. Could you confirm you can use jdbc/execute! on stmt -- no need for interop there?

@seancorfield seancorfield reopened this Sep 30, 2022
@seancorfield seancorfield self-assigned this Sep 30, 2022
@seancorfield seancorfield added the documentation The documentation is wrong or needs improving label Sep 30, 2022
@seancorfield
Copy link
Owner

Documentation updated on develop.

Don't forget to call .close on your Statement or use with-open when setting it up:

(with-open [con (jdbc/get-connection @datasource)
            stmt (prepare/statement con)]
      (jdbc/execute! stmt ["CREATE OR REPLACE EDITIONABLE TRIGGER ..."]))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation The documentation is wrong or needs improving
Projects
None yet
Development

No branches or pull requests

2 participants