ERROR [37000] [IBM][CLI Driver] CLI0118E Invalid SQL syntax. SQLSTATE=37000 - sql

I have a simple SQL statement query that is executed as command from C# code. It is targetting DB2. I created variables for the server/schemas as follows. It throws error.
private const string DB2Query
= #"SELECT Name as Name FROM {Schema}.Application WHERE ID = ?";
I get this error.
ERROR [37000] [IBM][CLI Driver] CLI0118E Invalid SQL syntax. SQLSTATE=37000
However, I don't get that error when executing from SQL as follows:
SELECT Name as Name
FROM MyServer..FOR3.Application
WHERE ID = 'MOM'
To support this, I tried to also do something like below in code, still throws different error.
private const string DB2Query
= #"SELECT Name as Name FROM {ServerName}..{Schema}.Application WHERE ID = ?";
It throws error on this line of code:
DataApplicationBlockHelper<string>.Get(db, dbCommand, Obj);
UPDATE
I found the culprit. It's not replacing the {Schema} placeholder. When I actually removed that from query and placed the schema name, it worked like a charm. It's a .net thing I believe? Can someone please help how to replace {Schema} with a value fetched from web.config?

While I can't really speak to the syntax of DB2 queries themselves, so I'll rely on your assertion that the query itself should work...
What you have in C# is simply a string and nothing more:
private const string DB2Query = #"SELECT Name as Name FROM {Schema}.Application WHERE ID = ?";
Note that there's no need for the # operator in this string definition, so let's simplify:
private const string DB2Query = "SELECT Name as Name FROM {Schema}.Application WHERE ID = ?";
While this string appears intuitively to have a placeholder that can be replaced with a value, if there's no code which does that anywhere then it won't happen. For that you have a few options. For example, you can use a placeholder that string.Format() understands:
private const string DB2Query = "SELECT Name as Name FROM {0}.Application WHERE ID = ?";
And then later in a method somewhere, when you want to use that string, apply the format value to it:
var sql = string.Format(DB2Query, someVariable);
In this case someVariable (which doesn't even need to be a variable and could be a string literal) would be used to replace the placeholder in the string.
Or, if you want to keep the named placeholder, you can potentially replace it manually:
private const string DB2Query = "SELECT Name as Name FROM {Schema}.Application WHERE ID = ?";
and later in a method:
var sql = DB2Query.Replace("{Schema}", someVariable);
This would observably accomplish the same thing, perhaps with an extremely minor performance difference.
You could also take advantage of both approaches by using the more recent language feature of string interpolation. This would use the $ operator to apply format placeholders in place directly. I don't think you can use this in a const, it's more for a local variable. Something like this:
var sql = $"SELECT Name as Name FROM {someVariable}.Application WHERE ID = ?";
This would still perform the same replacement, putting someVariable where the placeholder is, it's just using a more concise syntax than a call to string.Format(). One thing to note about this syntax is that it makes it look more like this interpolation is happening directly in-place on the string. It's still a multi-step process behind the scenes, which is why it likely won't work on a const or on class members at all (and should I imagine produce a compiler error).
Remember that strings are immutable, so any operation you perform which modifies a string would be returning a new string rather than modifying the existing one in place.
In any case, you'll of course also need to apply your query parameter for the ? placeholder. Note that what C# considers to be a placeholder in a string formatting/interpolating operation and what DB2 considers to be a placeholder for a query parameter are two entirely different things which happen at different times in different environments. (One in the .NET runtime, one in the database server's query execution.) But again, I'm relying on your assertion that the database query itself works and the only problem we're focusing on here is the C# string placeholder.

Related

Referencing column in Snowflake JS UDF

I created a JS UDF in Snowflake that has two inputs: a string from a column, and then another string that I use to create a mapping object.
Here's the function:
CREATE OR REPLACE FUNCTION function(supplier_name varchar, supplier_replace varchar)
RETURNS string
LANGUAGE JAVASCRIPT
AS
$$
regex_string = SUPPLIER_REPLACE.replace(/\b:\b/g, '":"').toLowerCase();
regex_final = '{"' + regex_string.replace(/\s*,\s*/g, '","') + '"}'
obj = JSON.parse(regex_final);
var supplier = SUPPLIER_NAME.toLowerCase();
for (var key in obj) {
if (supplier.includes(key)) {
var new_supplier = obj[key]
}
}
return new_supplier;
$$;
When I call the function in a SQL statement
select parent_supplier
, function(parent_supplier, 'Fedex:Fedex')
from table
I get the following error: "JavaScript execution error: Uncaught TypeError: Cannot read properties of undefined (reading 'toLowerCase') in TEST at ' const supplier = SUPPLIER_NAME.toLowerCase();' position 35 stackstrace: TEST line: 7".
I know this error is because I'm using a column as one of my input variables, but I can't figure out how to properly call it.
I'd appreciate any help!
Function works testing with a string as the input variable.
The error message claims the error is on a line reading this:
const supplier = SUPPLIER_NAME.toLowerCase();
However, there is no line like that in the UDF code in the question. Instead, the line closest to that line is this one:
var supplier = SUPPLIER_NAME.toLowerCase();
Since the line with the const does not appear in the UDF, this means it must be calling a different version of the UDF. There are a couple of common reasons why this happens. UDFs are owned by a directory and schema, and unless they're explicitly called using a three-part identifier (db_name.schema_name.udf_name), Snowflake will use the current schema in context and use that schema's UDF if there is one with that name and signature. The other reason is that Snowflake supports overloaded UDFs. That means that multiple versions of the same UDF name can exist provided they have different numbers of input parameters or different types of input parameters.
You can check to make sure the SQL is calling the right version of the UDF by placing something like return "foo" or some other recognizable return on the first line of the UDF temporarily. If calling it does not return that message (assuming there are no compilation errors) then it's running another version of the UDF.

Do I have to prefix sql parameter name with # sign when adding SqlParameters to the collection? [duplicate]

In one of our application the parameters passed to a stored procedure in this way
Dim parm As New SqlParameter("searchText", SqlDbType.VarChar)
parm.Direction = ParameterDirection.Input
parm.Size = 50
parm.Value="test"
cmd.Parameters.Add(parm)
and the procedure contains a parameter as #searchText
i.e. the parameter name passed from the code is searchText and that in the stored procedure is #searchText .
But it is working properly, I am always getting the required results.
So my question is like so there is no need to specify # before the parameter? Whether it will append #, can anyone please give an answer for this.
According to the documentation, the name must start with an #:
The ParameterName is specified in the form #paramname.
According to the source code (have a look at SqlCommand and SqlParameter.ParameterNameFixed in the reference source), an # is added automatically, if needed.
So yes, it works, but it's an undocumented feature. Best practice recommends that you do not rely on this and manually prefix your parameter name with an #.
Ref: SqlParameter.ParameterName Property and IDataParameter.ParameterName Property
The ParameterName is specified in the form #paramname. You must set ParameterName before executing a SqlCommand that relies on parameters. If you are using Sql Server as Database then you must specify # before
the parameter name.
your parameter name must be same as at backend eg. you have #searchText then in your parameter specification it must be SqlParameter("#searchText" ..
your code should be like this
Dim parm As New SqlParameter("#searchText", SqlDbType.VarChar)
parm.Direction = ParameterDirection.Input
parm.Size = 50
parm.Value="test"
cmd.Parameters.Add(parm)
Note: Oracle and SqLite use different use different character to specify parameter and there may be # symbol is not used specified by the specification of ado.net.
Edit: By comments
As you specified the link, it is also some sort of fix, but as per the msdn documentation, you must specify the positional parameter with '#' whether you are using any data provider oledb, sql, odbc. Ref
if (0 < parameterName.get_Length() && '#' != parameterName.get_Chars(0))
{
parameterName = "#" + parameterName;
}
Its not compulsory to specify the #. However, its a best practice.
Its similar in analogy to strings. There certainly is no harm in defining strings as such in .NET:
string s;
//Rest of the code follows;
But again, its a best practice to define them as :
string s = string.Empty;
You see, its a question of conventions and best practices!!!
I recommended you to use add "#" marker with your parameter name.
SqlParameter helps to add automatically, but others' parameter might not to.
Is the "#" symbol required? Yes and No. When you add a parameter using DbCommand, it's optional regardless of whether you're using SQL Server or not:
// Look Ma no # required!
DbCommand command = database.GetStoredProcCommand("StoredProctologistAndGambler");
database.AddInParameter(command, "Bet", DbType.Int32, fromLineNumber);
database.AddOutParameter(command, "Diagnosis", DbType.String, -1);
If you're going to reference the command later, however, the "#" prefix is required. Microsoft figured it was to hard to carry it over to the rest of the API.
var examResult = command.Parameters["#Diagnosis"]; // Ma! Microsoft lied! It requires the "#" prefix.

Call stored function without knowing the parameter names through vb.net

Can some one suggest me how to call a stored function in oracle through vb.net.
From vb.net should i able to pass the values to arguments of that function without knowing the parameter names?
Example: I have a function,
Create or Repalce Function Func_Name(param1 Varchar2,param2 varchar2)
Inorder to call this function through vb.net, we need to give
parameterargs.paramtername="param1"
Is there anyway so that i cannot use the parameter name and call the function
Thanks in advance
Rupesh
The way that we handled it was to open the Oracle DB up through an OleDbConnection, then call GetOleDbSchemaTable asking for the Procedure_Columns.
For example:
DataTable dtTable;
dtData = this.Connection.GetOleDbSchemaTable(OleDbSchemaGuid.Procedure_Columns, new object[] {null, null, sName, null});
foreach (DataRow theRow in dtData.Rows)
{
// Columns available in the row include:
// column_name, data_type, type_name, precision, and scale
}
Then, if you need to execute it without valid parameters (for example, to get the columns it exposes) you could execute it using DbNull.Value for each parameter.
Also, I can't remember exactly how Oracle operates, but in SQL Server you need to include the namespace when executing the function (i.e. select * from dbo.fn_my_test()). Also, depending on how the function is structured, you may have to select from it instead of executing it.
I'm not sure if you can use named parameters with Oracle.
When you create the parameterized query, try using question marks as a place holder:
Select col1, col2 From tablename Where col1 = ? and col2 = ?
Then, be sure to add the parameters to the command object in the correct order.
You don't need to know the parameter names to call it.
You need to know the number and type of them
Adding parameter names to the call means you don't have to pass all of them and / or you can pass them in a different order to the signature of the SP.
Call it like a parameterised query.
PSEUDOCODE
int customer_ID = 786;
Command.CommandText = 'Exec SP_MYProc #MyVar';
Command.Parameters.Add(new Parameter('MyVar',DbType.Int,customer_ID));
Command.Exec

Objective-C Strings

I am reviewing code that makes the following call:
id<PLResultSet> results = [sqliteDatabase executeQuery:#"select * where id=?",Id];
sqliteDatabase is an instance of PlausibleDatabase (from GoogleCode, I gather). The code works, but I don't understand it. Specifically, how does this section work?
#"select * where id=?",Id
Is the query being made with ? being replaced by Id? Or is the exeuteQuery function somehow combining the strings? How does this syntax make sense.
(Yes, I am new to Obj-C)
Thanks,
KF
This bit:
#"select * where id=?"
is an NSString (as opposed to a c-style string) which is being passed into a executeQuery: : method on the sqliteDatabase object. The second (unnamed) argument to the method is Id, presumably a local variable.
Guessing from the name of the method, the sqlite wrapper probably creates a parameterized query. The question mark is the syntax used by sqlite to mark where to insert the parameters.
It's specific to the method executeQuery, in which ? is used as a placeholder, and the appropriate positional argument is used as filler for that placeholder (with quoting, etc. added as necessary).

Argument Exception in DeriveParameters method

Dim id as integer = 1
Dim command as sqlcommand
Dim reader as idatareader
command = db.GetSqlStringCommand("select id, image, caption from profile where id = #id and image IS NOT NULL Order By NEWID()")
db.AddInParameter(command, "#id", DbType.Int32, id)
reader = db.ExecuteReader(Command)
The code is throwing an error I've never seen before....
SqlCommand.DeriveParameters failed because the SqlCommand.CommandText property value is an invalid multipart name "/port:4544 /path:"C:\sitepath" /vpath:"/sitepath"", incorrect usage of quotes.
How do I fix that error.
It looks like the code is failing at a deeper level than the code you have posted. I have received a similar error from within SQLServer Management Studio when I have not correctly defined the path to my DB.
How are you setting up the object 'db'?
What is your connection string? (Without password! :-))
The error is obviously related the badly formed string in terms of the quote positions. Do you know where entlib is constructing this string and how parts of it such as "C:\sitepath" are appearing with quotes as opposed to being appended as string literals?
I wonder if somewhere there is a declaration such as
Dim sRootPath As String = """C:\sitepath"""
..which is leading to the quotes being inserted into the constructed string.
I never saw this error, but perhaps this link helps: http://entlib.codeplex.com/Thread/View.aspx?ThreadId=60513
"What version of entlib is this? There's no overload in 4.1 for ExecuteReader that accepts an sql statement, there is one accepting a string but it should be the stored procedure name. Probably you are using this overload but I'm not sure since I'm getting a different error if I pass an sql statement"
I don't know about the error but the order by NEWID() bothers me a little. With newid() SQLServer calls the newid() function for each row in your dataset.