MySQL: Create a trigger keeps giving me syntax error - java

I've been trying to create a trigger from java and it just won't work.
String trigger = String.format("CREATE TRIGGER `%s` AFTER %s ON %s BEGIN INSERT INTO `ndb_log` (`table_name`, `action`, `time`) VALUES ('%s', '%s', UNIX_TIMESTAMP()) END;",
name, this.event.toUppercase(), this.table, this.table, this.event.toLowercase());
CREATE TRIGGER `onnc_censorINSERT` AFTER INSERT ON nc_censor BEGIN INSERT INTO `ndb_log` (`table_name`, `action`, `time`) VALUES ('nc_censor', 'insert', UNIX_TIMESTAMP()); END;
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'BEGIN INSERT INTO ndb_log (table_name, action, time) VALUES ('nc_censor' at line 1
I am not running this in phpMyAdmin, a server console or anything like that. I need to run it from java in a String. I call this.mysql.update(trigger); in my class which "basically" runs it.
I have tried running the create trigger string in ssh mysql, but it also doesn't work.

Two things: (1) you're missing the FOR EACH ROW clause of the trigger declaration; (2) you don't need the BEGIN and the END, because your trigger executes just one statement. Try this instead:
CREATE TRIGGER `onnc_censorINSERT` AFTER INSERT ON nc_censor FOR EACH ROW INSERT INTO `ndb_log` (`table_name`, `action`, `time`) VALUES ('nc_censor', 'insert', UNIX_TIMESTAMP());

Related

How to call a java class using mysql trigger

I was developing a code to sync data between multiple servers.
I wrote this MySQL trigger, so that it would trigger a java program if any change occurs to the table and sync it over to other servers.
If I run the below SQL code, I won't get any error and the java class is not being called.
use server1;
drop trigger if exists datainsert;
DELIMITER $$
CREATE TRIGGER datainsert
AFTER INSERT ON `student` FOR EACH ROW
begin
DECLARE id_exists Boolean;
DECLARE a INT;
SELECT 1
INTO #id_exists
FROM student
WHERE student.user_name= NEW.user_name;
IF #id_exists = 1
THEN
set a = sys_exec("java -cp \"E:\\servers\\Tomcat_instance1\\webapps\\Server\\lib\\*;E:\\servers\\Tomcat_instance1\\webapps\\Server\\WEB-INF\\classes;\" Test");
END IF;
END;
$$
DELIMITER ;
Insert query
use server1;
SET GLOBAL event_scheduler = ON;
insert into student values('l5','Test#123','asd','asd','M','20','coimbatore','654321','9876543210','a#123.com')
What am I missing here?
I have correctly linked the required library (lib_mysqludf_sys) file.

Java DbUtils MySQL How set param when call a stored procedures

I have a probleme with call a procedure, I want to set two paramams. In procedure first param have to be a int and secod time. I did this :
beans = (List) qRunner.query(conn, "call mpklocal.LCD_GetDispInfoChange_TEST(?, CURTIME() )", timtableId ,
new BeanListHandler(AnotherBusInBusStop.class));
when I close a program I see this :
Java.sql.SQLException: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT CURTIME())' at line 1 Query: call mpklocal.LCD_GetDispInfoChange_TEST(?,SELECT CURTIME()) Parameters: [657983]
at org.apache.commons.dbutils.AbstractQueryRunner.rethrow(AbstractQueryRunner.java:392)
at org.apache.commons.dbutils.QueryRunner.query(QueryRunner.java:351)
at org.apache.commons.dbutils.QueryRunner.query(QueryRunner.java:180)

Derby Transactions BEGIN and END

I created a trigger which works fine.
CREATE TRIGGER INSERT_USERID_TO_PERMISSIONS_TABLES
AFTER INSERT ON ALLUSERS
REFERENCING NEW AS NEW_USERID_ROW
FOR EACH ROW MODE DB2SQL
INSERT INTO ALLUSERS_HOMEPERMISSIONS(USERID)
VALUES(NEW_USERID_ROW.USERID);
Then I dropped it to recreate a new version of it that has 2 INSERT statements. When I added the other INSERT statement, it fails and returns an error. I know there's just some syntax error or keyword I missed. I googled it but can't get the equivalent of BEGIN and END (in MSSQL) for Derby.
So if I do,
CREATE TRIGGER INSERT_USERID_TO_PERMISSIONS_TABLES
AFTER INSERT ON ALLUSERS
REFERENCING NEW AS NEW_USERID_ROW
FOR EACH ROW MODE DB2SQL
INSERT INTO ALLUSERS_HOMEPERMISSIONS(USERID) --1st insert
VALUES(NEW_USERID_ROW.USERID);
INSERT INTO ALLUSERS_ADMIN_PERMISSIONS(USERID)-- 2nd insert
VALUES(NEW_USERID_ROW.USERID);
it returns an error.
I thought maybe I can add BEGIN and END
CREATE TRIGGER INSERT_USERID_TO_PERMISSIONS_TABLES
AFTER INSERT ON ALLUSERS
REFERENCING NEW AS NEW_USERID_ROW
FOR EACH ROW MODE DB2SQL
BEGIN
INSERT INTO ALLUSERS_HOMEPERMISSIONS(USERID) --1st insert
VALUES(NEW_USERID_ROW.USERID);
INSERT INTO ALLUSERS_ADMIN_PERMISSIONS(USERID)-- 2nd insert
VALUES(NEW_USERID_ROW.USERID);
END
I'd appreciate any help.
Thanks.

Java + MySQL - Syntax error but the statement is correct

My program executes INSERT query. When I run it, I get an error
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'INSERT INTO words(lang1, lang2, category, lang2_code, user) SELECT 'ahoj', 'hell' at line 1
I tried to print the actual statement to the stdout:
SET #lang:='Angličtina', #categ:='Nová';
INSERT INTO words(lang1, lang2, category, lang2_code, user)
SELECT 'ahoj', 'hello', c.id, l.id, 1 FROM categories c, languages l
WHERE c.name = #categ AND l.name = #lang;
As you can see, the statement is altered in the log. 'hell' instead of 'hello'. When I copy that into the mysql command line and execute, it works just fine so I assume the problem is in the JDBC somewhere.
That's not one statement. If you want to use more than one statement at a time, don't use a PreparedStatement but for example addBatch but it seems that here you should simply issue 2 JDBC statements, one after the other.

Create a oracle db trigger using thin jdbc driver

currently I setting up a test environment for an application. I'm using jUnit and Spring in my test environment. Before a test execution I want to set up a database test environment state. I already has written the SQL scripts (schema and data) and they runs fine in Oracles SQLDeveloper. As I tried to execute them by using the oracle thin jdbc driver, the execution fails. It looks like that the thin driver doesn't like create trigger statements.
I read that I have to use an oci driver instead of thin driver. The problem with the oci driver is that it is not platform independent and it takes time to set it up.
Example of my code:
CREATE TABLE "USER"
(
USER_ID NUMBER(10) NOT NULL,
CREATOR_USER_FK NUMBER(10) NOT NULL,
...
PRIMARY KEY (USER_ID)
);
CREATE SEQUENCE SEQ_USER START WITH 1 INCREMENT BY 1;
CREATE TRIGGER "USER_ID_SEQ_INC" BEFORE
INSERT ON "USER" FOR EACH ROW BEGIN
SELECT SEQ_USER.nextval
INTO :new.USER_ID
FROM DUAL;
END;
If I execute the the trigger statement the execution fails, but I looks like that the first part of the query (CREATE TRIGGER "USER_ID_SEQ_INC" ... "USER" ... BEGIN ... FROM DUAL;) is executed successfully, but the trigger seems to be corrupt if I try to use it. The execution fail error comes with the second part of the statement END; "ORA-00900: invalid SQL statement".
Do anyone know a solution for that problem? I just want to create a trigger with platform independent thin jdbc driver.
Cheers!
Kevin
Thank you guys for your answers, It works fine now. The reason was a syntax mistake or the interpretation of my SQL code file with Spring Framefork. When I execute the statements directly by using the execute method of jdbc it works, when I use the Spring functionality for script execution the execution fails. With oracle sql code it seems to be tricky, because if I use hsqldb sql code it works fine.
test-condext.xml:
...
<jdbc:initialize-database data-source="dataSource"
ignore-failures="DROPS" enabled="${jdbc.enableSqlScripts}">
<jdbc:script location="${jdbc.initLocation}" />
<jdbc:script location="${jdbc.dataLocation}" />
</jdbc:initialize-database>
...
schema.sql:
DROP SEQUENCE SEQ_USER;
DROP TABLE "USER" CASCADE CONSTRAINTS;
PURGE TABLE "USER";
CREATE TABLE "USER"
(
USER_ID NUMBER(10) NOT NULL,
CREATOR_USER_FK NUMBER(10) NOT NULL,
PRIMARY KEY (USER_ID)
);
ALTER TABLE "USER" ADD CONSTRAINT FK_USER_CUSER FOREIGN KEY (CREATOR_USER_FK) REFERENCES "USER" (USER_ID);
CREATE SEQUENCE SEQ_USER START WITH 1 INCREMENT BY 1;
CREATE TRIGGER "USER_ID_SEQ_INC" BEFORE
INSERT ON "USER" FOR EACH ROW
WHEN (new.USER_ID IS NULL)
BEGIN
SELECT SEQ_USER.nextval
INTO :new.USER_ID
FROM DUAL;
END;
/
ALTER TRIGGER "USER_ID_SEQ_INC" ENABLE;
This works fine! Its important to remove ; at the end of statements excepts the trigger statement!!!
#Before
public void executeSomeSql() {
Connection c;
try {
c = dataSource.getConnection();
c.createStatement()
.execute("CREATE TABLE \"USER\" (USER_ID NUMBER(10) NOT NULL, CREATOR_USER_FK NUMBER(10) NOT NULL, PRIMARY KEY (USER_ID))");
c.createStatement()
.execute("CREATE SEQUENCE SEQ_USER START WITH 1 INCREMENT BY 1");
c.createStatement()
.execute("CREATE OR REPLACE TRIGGER \"USER_ID_SEQ_INC\" BEFORE INSERT ON \"USER\" FOR EACH ROW WHEN (new.USER_ID IS NULL) BEGIN SELECT SEQ_USER.nextval INTO :new.USER_ID FROM DUAL; END;");
} catch (SQLException e) {
logger.debug(e);
}
}
Creating triggers works with any type of JDBC driver; there must be something wrong with the SQL syntax -- which is odd because Oracle should report that when you run the CREATE TRIGGER (not when you use it the first time).
Since you use BEGIN ... END; make sure that you really have a ; after END in the SQL which you send to the DB.
If that isn't the cause, check this article.
I know this is a old post but here's my answer.
By default, Spring "initialize-database" instruction split the specified script by using the semicolon character : ";".
In a trigger, there often is a semicolon inside the trigger, thus the queries are badly splitted and executed.
The solution is to use another split character ("|" for example) like this :
<jdbc:initialize-database>
<jdbc:script location="classpath:myscript.sql" separator="|"/>
</jdbc:initialize-database>

Categories