Getting an SQL Exception about being unable to convert one data type to another, but only when a field is too long? - sql

I have a massive stored procedure that I did not write. It's about 10K lines long. Part of it creates a few temp tables, inserts some records into these tables, then goes through about 8,000 lines of validation and removes invalid records from the tables and re-inserts them into a temp Error table for reporting back to the user.
Somewhere along the lines, I get the following SqlException in my C# code:
Conversion failed when converting the varchar value 'AAAAAAAABA683' to data type int.
But if I shorten the value down to just A683 or something, the procedure runs as expected and just marks this particular record as an error. So it sounds to me like it's not actually a problem with the data types, but something else.
Unfortunately the LineNumber property of the SqlException I catch doesn't help me, since I don't have access to seeing the actual SQL being executed. I can only look at the procedure itself.
Has anyone encountered something like this before?

When I get this error, it is because I am using + as a string concatenation operator, but one (or more) of the arguments is an integer. By the rules that SQL Server uses, if any argument is an integer, then the + is treated as addition rather than string concatenation.
Unfortunately, with a 10,000-line stored procedure you have few options (there could be a diatribe here about software engineering, making code more modular, and using constraints to validate data, but that would not be helpful).
What can you do? I don't actually know. You have a bug in your code, in the sense that the stored procedure is not expecting the types of values you are providing (and all the more ironic because it sounds like most of the procedure is validating values). Some logic in the stored procedure is changing the shorter value to something acceptable for numeric conversion, perhaps something like substring(val, 2, 5) and expecting the value to be an integer.
You could prevent the error by using the concat() function for string concatenation in the stored procedure rather than +. However, that might just hide some other error in the code. You could also prevent the error by pre-validating the data and preventing certain rows from being passed in.

Related

SQL data types for AnyLogic

I am saving the output of my AnyLogic model into an SQL server database. For non-AnyLogic aficionados, AnyLogic is based on Java. However, I am not sure what data types I need to specify for my columns in the database.
So far I am using these:
double in AnyLogic : float in SQL
string in AnyLogic : varchar in SQL
int in AnyLogic : int in SQL
I also have parameters that are of type Option list, which is, if I understand correctly, a form of Java enum. I tried to save those parameters as varchar, but this (obviously) does not work. In addition, my model contains various boolean parameters. For my boolean parameters, I add columns of type bit in SQL by running:
ALTER TABLE myTable
ADD my_bool BIT NOT NULL DEFAULT 0;
However, running the model returns this error
SQLServerException: Invalid column name 'false'. Caused by: Invalid column name 'false'
So concretely, how can I export parameters of type Option list and boolean?
This addresses the original question which was tagged MySQL.
I don't know all the issues around "option list". Seems like a string (with a length such as varchar(255)) would work. You can also look into the built-in enum type, although I would not normally recommend using enums.
I would recommend using boolean instead of bit as the equivalent for boolean. Seems more mnemonic.
That said, MySQL understands false as a constant. You can check this by running:
select false
This also works:
select "false"
However, this returns the error that you specify:
select `false`
I suspect that the code being generated is using this construct. You will need to look at the code -- and you might need to figure out some other way of handling this. In MySQL you can use 0 for false and that might fix your problem.
The AnyLogic database is a standard HSQLDB database (not something proprietary) but they've added AnyLogic client functionality to define 'column types' as though they are Java types (with special types for option lists and compiled-on-the-fly-and-run Java code).
If you look at the db.script file (HSQLDB just stores the persistent DB data as an SQL script which creates the tables and INSERTs the values) you can see the underlying HSQLDB types which map closely to SQL Server types.
boolean --> BOOLEAN
double --> DOUBLE
int --> INT
String --> VARCHAR(16777216)
Date --> TIMESTAMP
Code --> VARCHAR(16777216)
Option List --> VARCHAR(255)
NB: The 'Java column types' are supposed to make it easier for a non-technical user to understand what they will get from a Java perspective when querying that column but, for example, they are confusing in that queries will return Java nulls for missing values, so a boolean column actually effectively returns a Boolean.
That should help.
I managed to address part of my problem. I am now able to store String variables from Java into my SQL database. The issue was due to incorrect use of quotations.
Java uses double quotations for String variables (e.g.: ""). SQL expects single quotations (e.g.: '') for string-like columns such as varchar() and char()
I had to amend my SQL query to this:
String insertTableSQL = "INSERT INTO test (my_string) VALUES(" +" '"+my_variable_string+"' )";
Note that my_variable_string is a derivative of a Java enum, which I obtained by executing String my_variable_string= my_enum.name();

Syntax error in INSERT INTO statement

I am trying to insert some information in an MS Access database.
In my database I have the following columns and types:
log_order - Autonumber (I need this to keep the order where inserted in the db),
userID - Text,
time - Text,
date_ - text,
message - Text.
My query:
command.CommandText = "INSERT INTO logs(userID, time, date_, message) VALUES ('"+verifiedUser+"', '"+msg_time+"', '"+msg_date+"', '"+msg+"')";
OleDbDataReader reader = command.ExecuteReader();
The error that I get:
System.Data.OleDb.OleDbException: 'Syntax error in INSERT INTO statement.'
I tried several posts but no post helped me. I believe there might be a problem with the autonumber column (log_order). Because of what I remember I don't have to include it in the query.
PS: I know I have to pass the values as parameters.
Thank you in advance
Probably one of your variables (msg?) contains an apostrophe
The way you've written your SQL is a massive security risk. Please immediately look up "parameterized queries" and never, ever, ever write an sql like this again (where you use string concatenation to tack the values into the query). Your code has a proliferation of issues and using parameterized queries will solve all of them; they aren't difficult to write
It seems your data in some of the variables passed in INSERT may be causing this error. Try debugging the value in command.CommandText before executing it.
If any of the variables have a single quote they must be escaped...
Ref: How do I escape a single quote in SQL Server?
Also brush up on SQL Injection Ref: SQL Injection
I totally agree with all that has been said, but to answer your question directly, I am pretty sure you will need to put square brackets around your field names. OleDb tends not to like special characters and could well be having a problem for example with date_ ; sending [date_] instead should get round the issue.
It will not like time either. Same solution
Addendum on SQL Injection
As an aside, in fact calling Access through OleDb is relatively protected from SQL Injection. This is because any attempt to execute multiple instructions in one command fails. (You get an incorrect formatted string error). So whilst you could argue that what you are doing is safe, it is not for other db providers. The sooner you get into good habits, the less likely you will be to introduce a vulnerability in a case where it could be dangerous. If it seems like you are getting a stream of abuse, it is just because everyone here wants to keep the net safe.

SSIS Can't Store Decimal Output Into Variable (Execute SQL Task)

For the life of me I can't figure out how to store a decimal from a Stored Procedure into an SSIS Variable.
I have an Execute SQL Task that returns a result set. I mapped the column to the variable. I keep getting "Input string was not in a correct format". If I'm returning a decimal from my stored procedure and have the variable type as decimal. I would think this would work, but it doesn't.
Other things I've tried...
- Cast the column as a float and use variable double.
- Cast the column as a varchar and use variable string (succeeded but didn't store value)
- I've done variations on using Output instead of resultset but basically same issues.
Any ideas on how I can get this to work?
Thanks in advance!
As requested here are some screenshots:
This shows the assignment to the variable.
This is showing the variable as a decimal type.
This is showing the error received.
I didn't include the stored procedure but it defines vPreviousValue as a decimal(18,4) and returns it in the result set.
In case it may be helpful to someone else in the future...
After trying many variations I was able to figure out how to make this work.
I had the stored procedure output into a 'double' parameter.
I also found this link useful: http://milambda.blogspot.com/2014/02/sql-server-integration-services-data.html

Get ADODB to parse unicode in where clause, prefix with N

I'm updating one of our older applications to support unicode. It's littered with literal sql queries (SELECT * FROM ...) against the ADODB libraries. Most of this is working OK until I get to the SEEK code. We have some methods that transform user data into a where clause. So it parses a dictionary and produces a string. If the user is looking for something with unicode data I need to append the statement with an N. However, when I add this to the text and pass the command through the recordset.open, ADODB throws an exception :
Failed to Parse SQL
Existing SQL output:
SELECT * FROM ACCOUNT WHERE NAME ='ӐӕӔҔҖӸӽӳ'
this goes through the record set, but fails to retrieve any data.
What I need, but is throwing the exception:
SELECT * FROM ACCOUNT WHERE NAME = N'ӐӕӔҔҖӸӽӳ'
Is there some special magic I need to do to the record set to allow the N through? Or is there another approach I need to take for this to work? (and yes, I realize we SHOULD be parameterizing the queries and that's the long-term fix, but this is spaghetti code).

Trapping Exception using TSQLQuery & params

I am getting a "SQL Server Error: arithmetic exception, numeric overflow, or string truncation" error
here is the code below
AQuery:= TSQLQuery.Create(nil);
with AQuery do
begin
SQLConnection:- AConnection;
SQL.Text:= 'Insert into.....';
ParamByName('...').asString:= 'PCT';
.
.
.
try
ExecSQL;
finally
AQuery.Free;
end;
end;
I have alot of ParamByName lines, and I can't figure out which one is throwing the exception. I just know its thrown on the ExecSQL line. How can i tell which paramByName is causing the error?
When you have the metadata of the table, check the maximum length of string fields. When debugging, check the length of the strings you feed the parambynames. Also check the type of numeric fields, and make sure you don't exceed a maximum value. (I had this problem once with a string which length exceeded the varchars length in the table, and had this problem with a smallint databasefield that I tried to set to a too high value)
Get the SQL text after param substitution and run it as a query in SQL Server management studio.
You'll be able to debug it from there.
You are trying to insert a string value into a field that is not big enough to hold the value. Check the length of the values you are inserting against the length of the field in the table.
As others have said, it's almost certainly that you are pushing too-large a string into one of your fields. It could also happen with numeric values but it's most likely to be a string.
I'd suggest you temporarily alter each of your ParamByName('').AsString:=blah lines with a text constant, eg;
ParamByName('surname').AsString:='Smith';
ParamByName('firstname').AsString:='John';
etc, and see if you get an error. If it goes through without an error, then your problem is most likely to be that one of your string parameters is too long. Check your table schema and debug the actual strings you are putting into the parameters.
Depending on how much access (and experience) you have with this, you might find it more helpful to turn on the SQL Server logging such that you can see your queries (and the contents of those parameters) when the get processed by the SQL server. This will show you exactly what string and numeric values are actually being given to the server.
Which version/edition of SQL Server are you using?