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

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

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.

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

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.

Wha datatype is "System:VariableValue" in SSIS?

I need to log every change of variable values in a SSIS, at package level.
I have a SQL Task Editor that receives, as parameters, System::VariableName and System::VariableValue. I use this parameter to log a line in a DB log table.
Everything is working fine BUT... so far i only have numeric variables so, in the "Parameter Mapping", i specificed that the variable with name "System::VariableValue" is a NUMERIC DataType.
What happens when I will have a Datetime variable or a varchar variable? How can I handle variables of different types in this case?
Thankx
Make the datatype sql_variant, which will accommodate the different datatypes.
More on that here: https://msdn.microsoft.com/en-us/library/ms173829.aspx
Also, SSIS does have a on variable changed event which maybe helpful for you, though it sounds like you have a good custom solution.
m
EDIT:
So there is some documentation on MSDN that seems to suggest nvarchar maps to sql_variant. This worked for strings, but left the value empty for numeric values. Looking at the type for Variable.Value in the variables collection in a script task, it notes the type is empty. So I tried setting the data type to null, which did not work at all.
Finally, I created a script task to do the job and this worked correctly. The script task must call a stored proc in order for it to handle all the data types. I tested it with string, int, double and bool, all of which worked correctly.
Here is the table I used:
create table logging (myval sql_variant);
Here is the proc definition:
Create proc [dbo].[insertLog]
#myVal sql_variant
AS
Begin
set nocount on;
insert into logging values(#myVal);
end;
In the OnVariableValueChanged event handler, I added a script task with the following code:
using System.Data.OleDb;
public void Main()
{
// TODO: Add your code here
object val = Dts.Variables["System::VariableValue"].Value;
OleDbConnection conn = new OleDbConnection(Dts.Connections[".\\sql2016.Test"].ConnectionString);
using (conn)
{
conn.Open();
OleDbCommand cmd = new OleDbCommand("insertLog", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#myVal", val);
cmd.ExecuteNonQuery();
}
Dts.TaskResult = (int)ScriptResults.Success;
}
".\sql2016.Test" is the name of the connection manager in the package.
Please see if this will work for you,
m

How to execute a user defined function in SQL that has a paramter being passed to it?

I have a function that I created in SQL, and I need to test to make sure that its functioning properly. I know I can use something like...
SELECT * FROM dbo.TestFunction
to execute it, but how do I pass a parameter to the function?
Just call it with parameter as follows:
SELECT * FROM dbo.TestFunction (your_parameters_separated_by_commas)
If it's one parameter only, you call it as dbo.TestFunction(#param1). If it has multiple parameters, change to dbo.TestFunction(#param1,#param2...).

using Enterprise Library and adding output parameter differently

I am using Enterprise Library to query database and usin GetStoredProcCommand to query database. The problem arises when I want to use output parameter.
DbCommand cmd = db.GetStoredProcCommand("storedProcedureName", param1, param2, param3, ...);
Now, if I want to add output parameter, I can't simply write db.AddOutParameter(cmd, "#TotalNumber", DbType.Int64, sizeof(Int64));
I would have to add all the input parameters using db.AddInParameter(cmd, "param1", DbType.Int32, param1);
If you have 10 input parameters, adding them one by one in your code does not like alright and you just wish you could go back to adding them all in the same function call at once. Is there a way of doing this while also use output parameter?
Basically all you need to do is pass a null (or anything really) for the output parameter and you don't have to bother with db.AddOutParameter
From the comments on DbCommand GetStoredProcCommand(string storedProcedureName,
params object[] parameterValues)
The parameters for the stored procedure will be discovered and the values are assigned in positional order.
What they don't tell you is that count of the Db Parameters isn't the same as the params you'll get a Resources.ExceptionMessageParameterMatchFailure So for every output DB Parameter you still need to pass somthing.
What they also don't tell you is that when its assigning the value it checks the direction of the database parameter. If its output it just skips over your value.