mysql LOAD DATA LOCAL INFILE syntax error when executed via JDBC - java

I am trying to load contents from a csv file a local using this sample query:
SET GLOBAL local_infile=1; LOAD DATA LOCAL INFILE 'C:/afc_orders.csv' INTO TABLE `afc_report`.`afc_orders` FIELDS TERMINATED BY ';' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n' IGNORE 1 ROWS (`type_o`,`n_order`,`n_return`);
Executing the query from MySQL works perfectly but, when I try to execute the same query from JDBC, I get a syntax Error:
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 'LOAD DATA LOCAL INFILE 'C:/afc_orders.csv' INTO TABLE `afc_report`.`afc_orders` ' at line 1
Here is my code:
Connection conn = null;
String url = "jdbc:mysql://" + mysqlHost + ":" + mysqlPort + "/" + mysqlDatabase + "?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC";
try {
conn = DriverManager.getConnection(url, mysqlUser, mysqlPassword);
Statement stmt = conn.createStatement();
String sql = "SET GLOBAL local_infile=1; LOAD DATA LOCAL INFILE 'C:/afc_orders.csv' INTO TABLE `afc_report`.`afc_orders` FIELDS TERMINATED BY ';' OPTIONALLY ENCLOSED BY '\"' LINES TERMINATED BY '\\n' (`type_o`,`n_order`,`n_return`);";
System.out.println(sql);
stmt.execute(sql);
} catch(Exception e) {
System.out.println(e.getMessage());
}
And here is the driver I am using:
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.20</version>
</dependency>
What am I missing?

For future reference, I also had to add:
&allowLoadLocalInfile=true
to the connection string to avoid error:
ERROR 3950 (42000): Loading local data is disabled; this must be enabled on both the client and server side

Your code is attempting to execute two statements at once (the SET statement and the LOAD DATA statement), but a Statement.execute(...) only accepts a single statement, not multiple statements.
You could try to execute these statements separately (I don't normally use MySQL, so I'm not sure if that works in this case), or the MySQL Connector/J driver can be configured to allow multiple statements by adding the connection property allowMultiQueries=true in the connection string.

Related

load data query is not working with INSERT/REPLACE option

I am trying to upload data from CSV file into a mysql database table but i am getting error "java.sql.SQLException: Invalid utf8 character string: '' " when using INSERT/REPLACE option in load data query. but the same query works fine without INSERT/REPLACE option.
Query:
Statement stmt = conn.createStatement(
ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_UPDATABLE);
String query = "LOAD DATA INFILE 'D:\\"+flnm+"' REPLACE INTO TABLE prfl_hntr "
+ "FIELDS TERMINATED by ',' LINES TERMINATED BY '\n' IGNORE 1 LINES"
+ " (candidate, phone, mailid, skill, texp, rexp, pctc,np);";
stmt.executeUpdate(query);
I have verified the syntax in mysql documentation- https://dev.mysql.com/doc/refman/8.0/en/load-data.html.
Please note that i need to use REPLACE/IGNORE option in the query to eliminate duplicate entries.
You are right the issue is not with the syntax. The issue might be with difference in the characterset between Mysql table and your CSV file. I had a similar problem and resolved it by mentioning the characterset in the query. Try the query given below it should work and make sure your CSV file has data supported by Mysql table.
Query:
String query = "LOAD DATA INFILE 'D:\\"+flnm+"' REPLACE INTO TABLE prfl_hntr "
+"character set latin1 "
+ "FIELDS TERMINATED by ',' LINES TERMINATED BY '\n' IGNORE 1 LINES"
+ " (candidate, phone, mailid, skill, texp, rexp, pctc,np);";
stmt.executeUpdate(query);
Further you can follow the answer by #RolandoMySQLDBA for this question-: Trying to do LOAD DATA INFILE with REPLACE and AUTO_INCREMENT
It worked wonders for me.
LOAD DATA LOCAL INFILE '/home/xxxxx/conf.csv' INTO TABLE configuration FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n' IGNORE 1 ROWS;
try this once.

Can I run a "source" command (SQL script) from a JDBC connection?

I'm writing an application that has a data access layer to abstract the underlying connections to SQLITE3 or MySQL databases.
Thanks to some help here yesterday I was shown how to use a process builder to run a command line import into the SQLITE3 DB using output redirection.
Now I am trying to create the same database but in MySQL by importing a dump file. The load works fine from the command line client. I just tell it to source the file and the DB is created successfully.
However I am trying to do this through code at runtime and my method for executing a SQL statement fails to execute the source command.
I suspect that this is because "source" is not SQL but I don't know what else to use to try and run it.
My error message is:
java.sql.SQLSyntaxErrorException: 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 'source /tmp/ISMCoreActionPack_mysql.sql' at line 1
The failing command string:
source /tmp/ISMCoreActionPack_mysql.sql;
My method is:
public Boolean executeSqlStatement(String sql) {
Boolean rc = false;
try {
Connection connection = getConnection();
Statement statement = connection.createStatement();
rc = statement.execute(sql);
connection.close();
} catch (SQLException e) {
e.printStackTrace();
System.err.println(e.getClass().getName() + ": " + e.getMessage());
System.exit(1);
}
return rc;
}
Can anyone suggest how to do this?
You cannot run 'source' command, because it's not supported by JDBC driver, only MySQL.
My advice to you the following. Write some parser, which reads queries from a file, and executes them using JDBC statements.
source is not part of MySQL's dialect of SQL; it is a MySQL shell command. Still, you shouldn't need to write your own parser. You could use something like SqlTool as explained in this answer.

AWS mysql multiquery syntax error

I am porting a Tomcat7/Mysql applicationto AWS. I am seeing that whenever I send a multiple query statement I get an error like this:
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 ....
I have only detyected it on multiple queries (f.e. Multiple related deletes, like "delete from xxx; delete from xxx"). Single queries seem to work correctly.
I am using this code for the connection.
Class.forName("com.mysql.jdbc.Driver");
String jdbcUrl = "jdbc:mysql://" + hostname + ":" + port + "/" + dbName + "?user=" + userName + "&password=" + password + "&autoReconnect=true&allowMultiQueries=true";
Connection con = DriverManager.getConnection(jdbcUrl);
To run the query I have this code:
Statement st = conn.createStatement();
res = st.executeQuery(query);
conn.commit();
I have already set the allowMultiQueries=true but it is not working correctly. What am I doing wrong?
Is multiquery supported?
As pointed out by #jarmod, the problem was in the url and the separator. I should use & instead of &
&autoReconnect=true&allowMultiQueries=true

Can you use JDBC to connect to just an instance without specifying a database?

I am working on an JAVA app that evaluates the data and log sizes of all databases on an instance and mails a monthly report. I am currently working with SQLServer2014. I am using an SQL query that calculates the size of all databases by querying sys.master_files.
The problem is that when using JDBC to make the query, it returns the error:
java.sql.SQLException: No suitable driver found for jdbc:microsoft:sqlserver://localhost"
I have tried connecting to particular databases and that works fine. Is there any way to do this query directly to sys.master_files using JDBC? Or is there a smarter way altogether to accomplish the same result?
Thanks
Your "No suitable driver found" error is simply due to a malformed connection URL. jdbc:microsoft:sqlserver is not valid.
As for connecting to an instance without specifying a particular database, this works fine for me:
// NB: no databaseName specified in the following
String connectionUrl = "jdbc:sqlserver://localhost;instanceName=SQLEXPRESS;integratedSecurity=true";
try (Connection conn = DriverManager.getConnection(connectionUrl)) {
String sql = "SELECT name FROM sys.master_files WHERE type_desc='ROWS' ORDER BY database_id";
try (
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery(sql)) {
while (rs.next()) {
System.out.println(rs.getString(1));
}
}
} catch (Exception e) {
e.printStackTrace(System.err);
}
Note that sys.master_files is a system view that is available in all databases, so AFAIK it doesn't matter what the current database (catalog) is when you call it.

Teradata external Java Stored Procedure error: No suitable driver found for jdbc:default:connection

I wrote a Java stored procedure, packed it into a jar and installed it into the Teradata database. I want to use the default database connection as described here. Most of the code was generated by the Teradata wizard for stored procedures.
public class TestSql {
public static void getEntryById(int id, String[] resultStrings) throws SQLException {
Connection con = DriverManager.getConnection("jdbc:default:connection");
String sql = "SELECT x FROM TEST_TABLE WHERE ID = " + id + ";";
Statement stmt = (Statement) con.createStatement();
ResultSet rs1 = ((java.sql.Statement) stmt).executeQuery(sql);
rs1.next();
String resultString = rs1.getString(1);
stmt.close();
con.close();
resultStrings[0] = resultString;
}
}
I installed the jar:
CALL SQLJ.REPLACE_JAR('CJ!/my/path/Teradata-SqlTest.jar','test');
And created the procedure:
REPLACE PROCEDURE "db"."getEntryById" (
IN "id" INTEGER,
OUT "resultString" VARCHAR(1024))
LANGUAGE JAVA
MODIFIES SQL DATA
PARAMETER STYLE JAVA
EXTERNAL NAME 'test:my.package.TestSql.getEntryById(int,java.lang.String[])';
Now when I call this procedure, I get this error message:
Executed as Single statement. Failed [7827 : 39001] Java SQL Exception SQLSTATE 39001: Invalid SQL state (08001: No suitable driver found for jdbc:default:connection).
Now when I log off from Teradata and log on again and call the procedure, the error message becomes:
Executed as Single statement. Failed [7827 : 39001] A default connection for a Java Stored Procedure has not been established for this thread.).
What is the problem here? I'm connecting to Teradata using the Eclipse plugin. Teradata v. 15.0.1.01.
After many hours I finally found the problem. Eclipse packed all dependencies into the jar - which basically is ok. However it also packed the Teradata JDBC driver files (tdgssconfig.jar and terajdbc4.jar) into the result jar, which was the problem.
I adjusted the jar building process so that these files are not included and the errors went away.

Categories