I'm using a Spring jdbcTemplate.update(String sql, Object[] args) to execute a prepared insert statement on an Oracle database. One of the objects is a Character object containing the value 'Y', and the target column is of CHAR(1) type, but I'm receiving a
java.sql.SQLException: Invalid column type
exception.
I've debugged this backwards and forwards and there is no doubt that it is this one particular object that is causing the problem. The insert executes as expected when this Character Object is omitted.
I can also output the sql and Object[] values, copy the sql into sql developer, replace the value placeholders (?'s) with the actual values of the Objects, and the insert will work fine.
The sql (obfuscated to protect the guilty):
INSERT INTO SCHEMA.TABLE(NUMBER_COLUMN,VARCHAR_COLUMN,DATE_COLUMN,CHAR_COLUMN) VALUES (?,?,?,?);
The object values:
values[0] = [123]
values[1] = [Some String]
values[2] = [2012-04-19]
values[3] = [Y]
The combination run manually in sql developer and that works just fine:
INSERT INTO SCHEMA.TABLE(NUMBER_COLUMN,VARCHAR_COLUMN,DATE_COLUMN,CHAR_COLUMN) VALUES (123,'Some String','19-Apr-2012','Y');
The prepared statement sql itself is generated dynamically based on the non-null instance variable objects contained within a data transfer object (we want the database to handle generation of default values), so I can't accept any answers suggesting that I just rework the sql or insertion routine.
Anyone ever encountered this and can explain to me what's going on and how to fix it? It's frustratingly bizzare that I can't seem to insert a Character object into a CHAR(1) field. Any help would be much appreciated.
Sincerely, Longtime Lurker First-time Poster
There is no PreparedStatement.setXxx() that takes a character value, and the Oracle docs states that all JDBC character types map to Java Strings. Also, see http://docs.oracle.com/javase/1.3/docs/guide/jdbc/getstart/mapping.html#1039196, which does not include a mapping from Java char or Character to a JDBC type.
You will have to convert the value to a String.
Related
I am trying to pass a string value which is comma separated to birt report as parameter but failing
Java code
String userlist="\"a\",\"b\",\"c\"";
task.setParameterValue("userlist", userlist);
BeforeOpen has
params["userlist"].value.join("','");
SQL Query is
select * from users where name in (?)
I have already linked data set parameter to report parameter param_1
It's always giving me empty report even though DB table has 3 users. Any advise ?
Know your tools!
In this context: You have to understand SQL and the concept of bind variables, Javascript and BIRT.
Unfortunately every single piece of code you posted is wrong (or at least incomplete).
But you are on the right track: You can modify the SQL text in the beforeOpen event of the database. I'll sketch the idea here:
In your SQL, replace the ? with a placeholder like 'IN-LIST' (such that it is valid SQL).
You should still use the bind variable in the SQL (to avoid pitfalls caused by BIRT's caching mechanism), but in an effective no-op way, e.g. "where ? is not null".
In the beforeOpen event of the data set, you can modify the SQL text:
Get the original SQL text (var query = this.queryText; IIRC).
Split your report parameter into the individual search terms. How exactly to do this depends on your input format. In your example, you are using " around your search terms, which looks overly complicated, unless individual search terms may contain commas. You should now have a list of your search strings, e.g. ["a", "b", "c"].
Convert each term into a valid SQL string literal. Beware of SQL injection attacks, so carefully escape characters like single-quotes! You should now have a list of valid SQL string literals, e.g. ["'a"', "'b'", "'c'"].
Join your list of SQL string literals from 3) into a single string with ", ".
You should now have a string like 'a', 'b', 'c'.
In your query, replace your placeholder string with the string from 4).
Write the modified SQL text back to the DS object: this.queryText = query;
Probably there is also an example somewhere in the mists of the internet.
If you had invested five minutes more, you should have found an existing answer here on stack overflow: How to create a BIRT dataset that accepts multiple (CSV) values that it can be used inside "IN" clause in select statement, the only difference being that you are searching for a list of strings, while that question was about a list of numbers.
I am actually trying to insert the data in the H2 database. While starting up the application server, was getting the SQL syntax error exception. I am really not sure if H2 database supports the insertion of array in the column? Is there any issue with the below sql statement? Does H2 database support any of the array datatypes float[], String[]...?
INSERT INTO weather (id,date,temperature) values ('1','2019-09-11','{"37.3","36.8","36.4"}');
CREATE TABLE WEATHER(
id INT AUTO_INCREMENT PRIMARY KEY,
date DATE,
temperature text[]
);
You can't use PostgreSQL-style text[] as a data type in H2 and in other databases. H2 has the ARRAY data type for arrays:
https://h2database.com/html/datatypes.html#array_type
H2 1.4.201 will also support standard-compliant array data type with a component type:
componentDataType ARRAY[maximumCardinality]
You can build H2 from its current sources if you really need that functionality right now, but I think you don't really need it, non-standard plain ARRAY will work too.
'{"37.3","36.8","36.4"}' is a character string literal. H2 uses the standard array literals:
ARRAY[element, …]
https://h2database.com/html/grammar.html#array
If you use some outdated version of H2 you need to use non-standard (element, …) literal instead (but don't use that variant in recent versions, it will be parsed by them as a row value as required by the Standard).
It's not related with your question, but you really should use 1 instead of '1' as integer literal and DATE '2019-09-11' instead of '2019-09-11' as a date literal to avoid conversions from character strings to other data types.
I'm using Netbeans building a web application using Java, JSP that handle a database with Hebrew fields.
The DDL is as follows:
String cityTable = "CREATE TABLE IF NOT EXISTS hebrew_test.table ("
+"id int(11) NOT NULL AUTO_INCREMENT,"
+"en varchar(30) NOT NULL,"
+"he varchar(30) COLLATE utf8_bin NOT NULL,"
+"PRIMARY KEY (id)"
+") ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=1;";
String insert = "INSERT INTO hebrew_test.table (en, he) VALUES ('A','a')";
String insert2 = "INSERT INTO hebrew_test.table (en, he) VALUES ('B','ב')";
String insert3 = "INSERT INTO hebrew_test.table (en, he) VALUES ('C','אבג')";
executeSQLCommand(cityTable);
executeSQLCommand(insert);
executeSQLCommand(insert2);
executeSQLCommand(insert3);
The output tabel I get:
1 A a
2 B ?
3 C ???
Instead of:
1 A a
2 B ב
3 C אבג
I tried Hebrew appears as question marks in Netbeans, but that isn't the same problem. I get the question marks in the table.
Also I defined the table to be in UTF8_bin as you can see in the above code.
You need to tell the JDBC driver to use UTF-8 encoding while decoding the characters representing the SQL query to bytes. You can do that by adding useUnicode=yes and characterEncoding=UTF-8 query parameters to the JDBC connection URL.
jdbc:mysql://localhost:3306/db_name?useUnicode=yes&characterEncoding=UTF-8
It will otherwise use the operating system platform default charset. The MySQL JDBC driver is itself well aware about the encoding used in both the client side (where the JDBC code runs) and the server side (where the DB table is). Any character which is not covered by the charset used by the DB table will be replaced by a question mark.
See also:
Spring Encoding with CharacterEncodingFilter in web.xml
You're including your values directly into the SQL. That's always a bad idea. Use a PreparedStatement, parameterized SQL, and set the values as parameters. It may not fix the problem - but it's definitely the first thing to attempt, as you should be using parameterized SQL anyway. (Parameterized SQL avoids SQL injection attacks, separates code from data, and avoids unnecessary conversions.)
Next, you should work out exactly where the problem is really occurring:
Make sure that the value you're trying to insert is correct.
Check that the value you retrieve is correct.
Check what's in your web response using Wireshark - check the declared encoding and what's in the actual data
When checking the values, you should iterate over each character in the string and print out the value as a UTF-16 code unit (either use toCharArray() or use charAt() in a loop). Just printing the value to the console leaves too much chance of other problems.
EDIT: For a little context of why I wrote this as an answer:
In my experience, including string values as parameters rather than directly into SQL can sometimes avoid such issues (and is of course better for security reasons etc).
In my experience, diagnosing whether the problem is at the database side or the web side is also important. This diagnosis is best done via logging the exact UTF-16 code units being used, not just strings (as otherwise further encoding issues during logging or console output can occur).
In my experience, problems like this can easily occur at either insert or read code paths.
All of this is important as a way of moving the OP forward, not just in a comment-like request for more information.
I'm converting (or trying to) an Ms AccessDB into derby.
When I extract the data from certain varchar / text / memo field from access they are filled with apostrophe, and mathematical symbols (percent, less than etc), and possible foreign characters
I need to keep these and I test for them so as I can use an 'escape sequence' to ensure they get put into the database.
However for now I am unable to get the data into the DB without it failing on these fields. When the SQL fails I output the SQL string, and cut and past it into ij. Then I modify just the first record, and it is always these characters that cause me grief.
I've tried to modify the strings by surrounding with "double quote marks" but that just gives a different error (stating that it has 'enounterd """ at line1 column x' which is always the first occurance of the double quote).
I haven't found a setting in derby to alter the behaviour for strings, yet. Is there one?
I have also tried to set the SQL statment to a preparedStatement then use the {call preparedStatement} again this fails also. I can't use the {escape "escape char} in a normal statment as derby just says incorrect syntax at me.
How do others manage to get user content with strange characters into a field in derby?
Do I need to change my field into a CLOB or something other than varchar / long Varchar?
Are my problems being caused by using the wrong characteset (eg iso rather UTF-8), how do I tell what it is, how to change it?
Below is a sample of the SQL insert that fails when I send it to derby (via my JAVA 'programme')
insert into S1.SORTIEDESSAI (OBS, DATEDUSORTIE, CONTREINDIC, FIN,
PDEVU, REFUS, INVDECISN, ADMIN, MOTIF_DE_LA_SORTIE, NOMVALIDEE,
DATEVALIDEE) values ('"0001/0001"' , '2007-07-15' , false , true ,
'"null"' , '"null"' , '"null"' , '"null"' , '"2. FIN DE L’ESSAI"' ,
'"DR SIMON"' , '2011-04-19' )
Note:
Actually I look at the above and notice that the order of columns names isn't good? It was OK yesterday, not sure why it would have changed? something to do with Access returning the column names in a random order from the resultSetMetaData, which would be a surprise.
for now I recomend any further answers to hold off whilst I sort this problem out, OK solved that problem, do I need to set another question about this behaviour....
Back to the main thread...
Ok as you can see on my SQL statement I have wrapped any varchar fields in double quotes. This always fails (even directly through ij). help help help...
I'm not quite sure what your question is, but in general you can input these characters by using a PreparedStatement of the form: INSERT INTO tablename (columnname) values (?), and then using the PreparedStatement.setString() method to supply your character data for that column.
I have a field with varchar(100) in mysql, I want to store first 100 characters because my data length is 200 characters(ignore last 100 character).I doesn't want to change my source code. Which is possible in MS-Access and MS Server but I want to do this in mysql.
I am applying this in java with hibernate, means I am not writing insertion code for this. Here I am just using save() method and its throwing "Large data".
I have got Exception-
Caused by: java.sql.BatchUpdateException: Data truncation: Data too long for column 'FBUrl' at row 1
at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1527)
at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1065)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:58)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:195)
glb.chatmeter.exception.AdException: Could not Save Facebook page Data.
Note: An hour after the below, the question was edited with a substantial change. This answer answered the question as it was originally, but doesn't address the edited version.
You can use substring:
INSERT INTO MyTable (Myfield) values (SUBSTRING('long string', 1, 100))
The pos parameter starts at 1 (oddly), and it's okay if the len parameter is larger than the length of what you're actually inserting.
You can use SUBSTRING() to trim inserts:
INSERT INTO table (column) VALUES (SUBSTRING("your data...", 1, 100))
try this
SELECT INSERT('your string', 0, 100, '');
REFERENCE
The only way to do it without changing the source code is to fiddle with the configuration of the MySQL server. More specifically, the sql_mode variable:
http://dev.mysql.com/doc/refman/5.1/en/server-sql-mode.html
I believe you have to set STRICT_TRANS_TABLES:
For STRICT_TRANS_TABLES, MySQL
converts an invalid value to the
closest valid value for the column and
insert the adjusted value. If a value
is missing, MySQL inserts the implicit
default value for the column data
type. In either case, MySQL generates
a warning rather than an error and
continues processing the statement.
Implicit defaults are described in
Section 10.1.4, “Data Type Default
Values”.
However, it's important to note that this setting will affect many other things. The only reason I see not to change the source code is that you don't have access to it, and in such case you can probably just enlarge the DB column.