Why am i getting a syntax error with this prepared statement? - prepared-statement

I am trying to learn how to do a PreparedStatement as follows:
createConnection();
conn.setAutoCommit(false);
String sql = "SELECT MAX(?) FROM ?";
PreparedStatement stmt = conn.prepareStatement(sql);
However, when I hit the last line, it throws a java.sql.SQLSyntaxErrorException as follows:
java.sql.SQLSyntaxErrorException: Syntax error: Encountered "?" at line 1, column 20.
I have searched everywhere but cant find any reason for it to fail. What am I doing wrong? later on in the code I am setting the ? parameters as meaning full string values but when I debug I never get to that point. It hits this conn.prepareStatement line and throws the exception. Thanks for the help. I don't know if it makes a difference but it is on a derby database.

Think of your ? mark as a sql variable. You can't do a select MAX on a variable, it's syntactically incorrect.
You can't do the following:
declare #myvar int
select #myvar = 1
SELECT MAX(#myvar) from SomeTable

Related

SQL Server Float Datatype out of range

I have a query that I captured through an extended events session with a float datatype that looks like :
#variable = 120700.8000000000000000000000000000000000000000000000
If I try to run the same query in SSMS, I get the error:
The number '120700.8000000000000000000000000000000000000000000000' is out of the range for numeric representation (maximum precision 38).
Same as if you were to run
DECLARE #variable float = 120700.8000000000000000000000000000000000000000000000
The query succeeded when the trace was running. The Event is rpc_completed and it has a duration, cpu, rowcount, etc...
Not sure if this is relevant, but the query in question is an exec sp_executeSQL. The full query as captured by the trace looks like:
exec sp_executeSQL N'SELECT
col1,
col2
FROM table
WHERE col3 > #variable', N'#variable float',
#variable = 120700.8000000000000000000000000000000000000000000000
So my question is, why is the code in the trace able to execute without error, but when I copy/paste that same code to SSMS it throws an error. If I take that same code and trim off a bunch of those zeros it works.
I am running on SQL Azure DB. I have reproduced on compatibility SQL2016, SQL2019, and on Prem SQL2019.
why is the code in the trace able to execute without error, but when I
copy/paste that same code to SSMS it throws an error.
When you put this query in SSMS
exec sp_executeSQL N'SELECT
col1,
col2
FROM table
WHERE col3 > #variable', N'#variable float',
#variable = 120700.8000000000000000000000000000000000000000000000
the literal 120700.8000000000000000000000000000000000000000000000 is interpreted as a numeric/decimal type. The engine tries to convert it to a value of numeric/decimal type and fails, because numeric has maximum precision of 38 digits.
If you put this query in SSMS, it should work
exec sp_executeSQL N'SELECT
col1,
col2
FROM table
WHERE col3 > #variable', N'#variable float',
#variable = 120700.8000000000000000000000000000000000000000000000E0
I've added E0 at the end.
To make the float literal we need to use the scientific notation, as documented in Constants (Transact-SQL)
why is the code in the trace able to execute without error
I can't say for sure, but I suspect that the code that you see in the trace is not exactly the same code that was sent to the SQL Server by the application. It could have been sent in such a way that the parameter type and value was actually float, not a text string with all these zeroes.
I think, the application is likely to make an RPC call passing proper parameter with proper type to the function call. So, there was never a conversion from a text string to numeric or float type when an application made this successful call.
The string literal 120700.8000000000000000000000000000000000000000000000 is first implicitly converted to decimal, hence the error.
Try
DECLARE #variable float = 120700.8000000000000000000000000000000000000000000000E0
Source: TSQL - make a literal float value
Details on what I did to proof out the accepted answer above.
I was taking the trace statement and replaying it on another DB using C# like this (this will throw the out of range error):
cmd.CommandType = System.Data.CommandType.Text;
cmd.CommandText = "exec sp_executesql #stmt=N'SELECT #f',
#params=N'#f float',#f=120700.800000000002910383045673370361328125";
cmd.ExecuteNonQuery();
What I need to do is extract those parts and build a stored procedure with parameters like this :
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.CommandText = "sp_executesql";
SqlParameter p1 = new SqlParameter();
p1.DbType = System.Data.DbType.String;
p1.ParameterName = "#stmt";
p1.Value = "SELECT #f";
SqlParameter p2 = new SqlParameter();
p2.DbType = System.Data.DbType.String;
p2.ParameterName = "#params";
p2.Value = "#f float";
SqlParameter p3 = new SqlParameter();
p3.DbType = System.Data.DbType.Double;
p3.Value = 120700.8000000000000000000000000000000000000000000000;
p3.ParameterName = "#f";
cmd.Parameters.Add(p1);
cmd.Parameters.Add(p2);
cmd.Parameters.Add(p3);
cmd.ExecuteNonQuery();
When I run that, it shows up in the trace as:
exec sp_executesql #stmt=N'SELECT #f',#params=N'#f float',#f=120700.800000000002910383045673370361328125
So the issue is that I cannot just take the statement from an rpc_completed event. I need to parse it and reconstruct the stored procedure explicitly.

How to execute dynamic SQL in .net?

I'm trying to write the SQL execute statement below. I'm getting an error in .net saying
An exception of type 'System.Data.SqlClient.SqlException' occurred in System.Data.dll but was not handled in user code
Additional information: Invalid column name 'Survey'
There is no Survey column which is correct, but what is crazy is that it is getting that value from the #SurveyNumber variable. I think my exec code is correct, but maybe I'm not escaping the #SurveyNumber properly?
The #SurveyNumber variable contains this string "Survey - 1234"
#SurveyNumber varchar(50),
#RefIds varchar(max)
AS
Begin
exec('SELECT
Distinct
r.DRAWING,
r.[DESC],
r.REFMEMO,
r.OP_PSI,
r.MAX_PSI,
r.MAX_TEMP,
r.DESIGN,
r.CORR_RATE,
r.MIN_INSP,
r.INSP_LOC,
r.REPL_DATE,
r.LAST_INSP,
r.NEXT_INSP,
r.ALLOW_PSI,
IIf( r.[CF1] is null Or r.[CF1]='''',''Max'', IIf(r.[CF1]=''L'',''Long'',IIf(r.[CF1]=''S'',''Short'',IIf(r.[CF1]=''U'',''User'',''NA''))))AS CF1,
r.[NF2]*1000 as NF2,
r.CF2,
r.V_Last_Insp,
r.V_Next_Insp,
r.V_Concern,
r.V_Memo,
r.V_Report,
r.V_Interval,
r.Insulated,
r.AVG_NEXT_INSP,
r.AVG_REPL_DATE,
r.Scaffolding,
r.Number_Xrays,
r.MIN_RMS,
r.DRAWING_FLAG
From ref r
where r.SurveyNumber = ('+#SurveyNumber+') and r.Id In ('+#RefIds+')
ORDER BY r.NEXT_INSP asc')
End

WSO2 DSS Update Statement Parameter com.microsoft.sqlserver.jdbc.SQLServerException: Incorrect syntax near ':'

I am performing the following SQL Update statement in WSO2 DSS
Update Door
Set dcr_messageBox = :msg, dcr_servicesArea = :servArea
Where dcr_regNo = :regNo
I am exposing this query as a rest service. I keep getting the following error
Current Request Name: _putdoorproperty
Current Params: {servArea=21, regNo=313, msg=21}
Nested Exception:-
com.microsoft.sqlserver.jdbc.SQLServerException: Incorrect syntax near ':'.
</soapenv:Text></soapenv:Reason><soapenv:Detail><axis2ns646:DataServiceFault xmlns:axis2ns646="http://ws.wso2.org/dataservice"><axis2ns646:current_params>{servArea=, regNo=3123, msg=}</axis2ns646:current_params><axis2ns646:current_request_name>_putdoctorproperty</axis2ns646:current_request_name><axis2ns646:nested_exception>com.microsoft.sqlserver.jdbc.SQLServerException: Incorrect syntax near ':'.</axis2ns646:nested_exception><axis2ns646:source_data_service>
Anyone has any ideas what it may be?
I've tried this out, since a colleague of mine also has this problem right now. It seems that the problem is caused because of the carriage returns (enter) in the statement.
Try it like this, without any carriage returns:
Update Door Set dcr_messageBox = :msg, dcr_servicesArea = :servArea Where dcr_regNo = :regNo
This worked for me.
JC
In JDBC, the default placeholder for variables is ?. The common use of named parameters like :msg is not supported (by standalone JDBC)
You'd need to transform your query to
Update Door
Set dcr_messageBox = ?, dcr_servicesArea =?
Where dcr_regNo = ?
and then perform on your PreparedStatement
ps.setInt(1, msg);
ps.setInt(2, servArea);
ps.setInt(3, regNo);

CodeIgniter SQLite where field IN array condition

I'm having some trouble trying to set a 'WHERE field IN ...' clause in CodeIgniter using SQLite. I got an array of all where clause conditions called $conditions, and added the WHERE IN clause in this way:
$this->browse_model->conditions['username IN'] = "(SELECT like_to FROM likes WHERE like_from = '".$this->user->username."')";
and inside of my browse_model I use the following code to run the query:
$get = $this->db->get_where('users', $this->conditions, 6, $_SESSION['browse_page']*6);
but somehow when I use the condition I wrote above it is giving me the following error:
Fatal error: Call to a member function execute() on a non-object in
../www/system/database/drivers/pdo/pdo_driver.php on line 193
As far as I'm concerned the 'field IN array' statement is allowed in SQLite too, so I really don't know why this isn't working. Does anyone know how to make this work?
Thanks in advance!
Greets,
Skyfe.
EDIT: Tried setting the condition in the following way and didn't get an error but neither any results:
$this->browse_model->conditions['username'] = "IN (SELECT like_to FROM likes WHERE like_from = '".$this->user->username."')";
So I guess that's still not the correct way to do it..
EDIT2: 'Fixed' it, somehow it didn't interpetate the field => value way of notating the where clause correctly for the IN statement, so defined it in a custom string:
$this->browse_model->custom_condition = username IN (SELECT like_to FROM likes WHERE like_from = '".$this->user->username."')
Their is some problem in formatting IN clause,
SELECT * FROM users WHERE gender = 'f' AND gender_preference = 'm' AND username IN (SELECT like_to FROM likes WHERE like_from = 'testtest')

CAST error in a Where Clause

On the query below I keep getting this error:
Cannot read the next data row for the dataset DataSetProject. (rsErrorReadingNextDataRow)
It appears to be the where clause, if I take it out it seems to work. So I added a cast to the where clause with no luck. Is there something special I need to do in the where clause to get this to work? Just an FYI this is in a report that is pulling an id from the url.
SELECT new_projects.new_projectsId AS ProjectId
, new_projects.new_name AS ProjectName
, new_projects.new_Description AS ProjectDescription
FROM
new_projects
LEFT OUTER JOIN new_projectsteps
ON new_projects.new_projectsId = new_projectsteps.new_ProjectSteps2Id
LEFT OUTER JOIN Task
ON new_projectsteps.new_projectstepsId = Task.RegardingObjectId
WHERE
(new_projects.new_projectsId = cast(#id AS UNIQUEIDENTIFIER))
Thanks!
EDIT:
The id in SQL is a Unique Identifier, the value of #id is being pulled from the querystring(url). So it would look like: &id='BC02ABC0-A6A9-E111-BCAD-32B731EEDD84'
Sorry for the missing info.
I suspect the single quotes are coming through. So either don't have them there by stripping them out before being passed to your parameter or use:
WHERE new_projects.new_projectsId = CONVERT(UNIQUEIDENTIFIER, REPLACE(#id, '''', ''));
If you try a direct comparison when the GUID contains other characters, you should get:
Msg 8169, Level 16, State 2, Line 1 Conversion failed when
converting from a character string to uniqueidentifier.
If this is not what's happening, then don't say "the id in SQL is a Unique Identifier" - show ALL of the code so we can try to reproduce the problem.

Resources