I am working in a previously existing grails project that has some search functionality built into it. It has created a new Sql object using my SQL Server datasource, and it seems like it is attempting to call a stored procedure like so:
def qResults = sql.rows(spCall)
where spCall is a String and looks like this:
EmployeeQueryClient 'SomeClient', 1,1,0
Where "EmployeeQueryClient is the name of the stored procedure, and the other things are the parameters.
I can't find any documentation supporting this kind of call - is this correct? How would I really do this if it is not?
In the code shown above sql is an instance of groovy.sql.Sql. This provides a rows(String sql) method that can be used to execute SQL and returns the result.
Generally speaking, I think this rows method is a bad choice if you want to call a stored proc, because you have to concatenate the name of the proc and all the args into a single string, which is a bad idea from the point of view of both type safety and readability.
Instead use one of the overload call methods provided by the same class, which are specifically intended for invoking stored procedures. For example, if you just want to invoke the procedure (ignoring any results it returns) use:
sql.call("{call EmployeeQueryClient(?, ?, ?, ?)}", ['SomeClient', 1, 1, 0])
The syntax used here for calling a stored proc,
{call PROC_NAME(PROC_ARGS)}
will work for MySql. If you're not using MySql you'll need to replace this with whatever is used by your RDBMS to invoke a stored proc.
Overloaded versions of the call method enable you to handle any results returned and/or ouput parameters of the stored proc.
Related
I am trying to find a way to write a stored procedure that will take a list of nvarchar's as an input parameter. There can be one to finite amount of items in the list.
I also am not sure how to call a stored procedure from C# as a list, I am use to using data types like int or string.
Stored Procedures are being managed by Sql Server 2018
From a great reply:
in PostgreSQL, CREATE FUNCTION is indeed a "SQL statement" but is is merely a
"wrapper" to specify a block of code that is executed by something
different than the SQL query "engine". Postgres (unlike other DBMS)
supports multiple "runtime engines" that can execute the block of code
that was passed to the "CREATE FUNCTION" statement - one artifact of
that is that the code is actually a string so CREATE FUNCTION only
sees a string, nothing else.
What are the consequences of "the code is actually a string so CREATE FUNCTION only sees a string, nothing else"?
Is that considered as dynamic SQL? Does it prevent or introduce SQL injection risk, compared to dynamic SQL?
How is that different from other RDBMS (if any?) where "the code is not a string"?
Thanks.
PostgreSQL is highly extensible, and you can for example define your own procedural language to write functions in.
PostgreSQL knows nothing about the language except that it has to call a certain language handler to execute the function.
The way that was chosen to implement this is to simplify pass the code as a string.
This is just an implementation detail and does not make PostgreSQL functions any more or less vulnerable to SQL injection than other RDBMS.
There are several levels on which you have to defend yourself against injection:
The function arguments: Here you should choose non-string data types whenever possible.
The SQL statements within the function: Here you should avoid dynamic SQL whenever possible, and if you have to use dynamic SQL, you should insert variables using the %L pattern of the format function.
Again, this is the same if function bodies are specified as strings or not.
All 3GL+ code is basically a string. The "parameter" passed to CREATE FUNCTION is code (to be executed outide the core SQL engine), which is a string (that's not SQL).
Other RDMS's only support SQL as the function/procedure body.
My simple question is as follows:
If I have a Microsoft Access database with a defined "query" in it (i.e. the kind of database object that MS Access calls a Query, just to avoid any ambiguity) defined to take parameters (using a PARAMETERS declaration inside its SQL definition) what is the correct SQL syntax to call it over an ODBC connection, including providing the parameter values?
EDIT / ADDITION:
I just noticed that it could be done by adding curly-braces around the entire CALL command, as follows:
{CALL myAccessQuery ('string1', 'string2', 'string3')}
This was actually exactly what they already did in the other related SO thread that I'm referring to here below, but I just thought that this was some C#-specific magic related to the prepared-statement nature of their SQL statement (using "?" in it), or some other peculiarity of their SQL library (I'm not using that language), so I previously ignored it.
Anyone who will explain what the curly-braces are, and why they allow for execution of more SQL commands than the explicitly stated supported ones in the error message below, will be an accepted answer for this question.
Some more details for my specific case:
My query takes three parameters, defined by a "PARAMETERS" clause in the beginning of the query's declaration, as so:
PARAMETERS myParam1 Text ( 255 ), myParam2 Text ( 255 ), myParam3 Text ( 255 );
SELECT ... <a bunch of not relevant stuff here> ;
Using an (already established and confirmed working) ODBC connection, I want to use this query from an external application, including providing the required three parameters for it.
Running normal queries like SELECT etc works just fine over the connection from my external application, but no matter how much I google, I cannot seem to find out the proper way to correctly provide the parameters for and run my query? So, again, my question is, what is the correct SQL syntax for doing this?
NOTE: I do NOT want any API specific solution for some certain library or similar, since this only solves the problem for a very small part of all developers who want to do this from different programming languages, so for this reason, I won't even bring up what language my external application is written in. I just want the full SQL syntax for doing this, nothing more, nothing less.
Another SO question indicates that this should be done using the "CALL" keyword, but when I try to use this from my application, I just get the following error message:
[42000] [Microsoft][ODBC Microsoft Access Driver] Invalid SQL statement; expected 'DELETE', 'INSERT', 'PROCEDURE', 'SELECT', or 'UPDATE'.
I.e., this is the "SQL command" (purposely avoiding the ambiguous term "query"...) that I'm trying to execute when getting this error:
CALL myAccessQuery ('string1', 'string2', 'string3')
The only one of the SQL keywords mentioned in the error message that seem likely to be useful is the "PROCEDURE" keyword, but I'm having similarly big difficulties finding any relevant documentation also for this on Google. :-(
I suspect that most of Google's lack of results in regards to this entire scenario comes from the many involved ambiguities regarding more or less all the central keywords in the context, like "queries", "parameters", "execute", "call" and "procedure", so with this SO question my hope is that it will constitute a somewhat more easily identified and indexed answer for this question to be presented by Google in the future.
When you're connecting over ODBC, look at the driver-specific information to see if it supports the various ODBC extensions (indicated by curly braces in the ODBC calls):
https://msdn.microsoft.com/en-us/library/ms675326(v=vs.85).aspx
Specifically:
ODBC provides a specific syntax for calling stored procedures. For the CommandText property of a Command object, the CommandText argument to the Execute method on a Connection object, or the Source argument to the Open method on a Recordset object, passes in a string with this syntax:
"{ [ ? = ] call procedure [ ( ? [, ? [ , … ]] ) ] }"
Each ? references an object in the Parameters collection. The first ? references Parameters(0), the next ? references Parameters(1), and so on.
The parameter references are optional and depend on the structure of the stored procedure. If you want to call a stored procedure that defines no parameters, your string would look like the following:
"{ call procedure }"
The Access ODBC driver exposes saved SELECT parameter queries as Stored Procedures, so that's why you use this syntax.
We are using edge-sql to execute T-SQL scripts and also stored procedures via C#. I noticed recently that stored proc support has been added and I'm trying to execute would would be:
exec dbo.sgRouteExportDelete #TripDate='2014-05-06', #RouteId = 1234, #Action='DELETE', #Comment='xxxxxx';
in SQL Server Management Studio, using edge-sql 0.1.2.
I've played around with several variations, but I get one of 2 error messages. Either cannot find stored procedure '' or "cannot find stored procedure 'sgRouteExportDelete #TripDate='2014-05-06', #RouteId = 1234, #Action='DELETE', #Comment='xxxxxx'" The stored proc executes just fine in edge.sql when invoked via C# method.
I did some additional experimentation and found I can execute a stored proc with no parameters: exec dbo.sgVersionGet, but any stored procs with parameters return errors.
So what am I doing wrong? And how could I invoke with parameter values that aren't hard-coded, as above? Both SQL Server and edge use the # character for parsing params.
Any help appreciated ...
-BillyB
In SQL Server when you are referring to a database object without the object full path ([database.schema].object), SQL Server will try to locate the object using the Default/Initial Catalog value which points to the default database if that was not specified within the connection string then chances are that when you try running your statement SQL Server won't be able to find the object throwing the "Cannot find XX" error, You should either specify an initial catalog on your connection string or execute your procedures using the full path, database.schema.procedure E.g. mydatabase.dbo.sp_customerCleanUp. On the other hand there is an internal procedure sp_executesql that you can use to run your procedures without having to hard code the parameters, all you need to do is build a string concatenating the hard coded part of the string (the procedure name) and whatever number of variables you are passing as parameters, see example ( https://technet.microsoft.com/en-us/library/ms175170%28v=sql.105%29.aspx )
The variables are assumed when calling a stored procedure with edge-sql. Any parameter you would preface with an '#' symbol will need to have the same name within the stored procedure.
I have an Oracle function that returns a nested table of an Oracle user defined type.
If I call the function from TOAD or SQL developer with a syntax like this:
SELECT * FROM TABLE(MYFUNCTION('SOME_STRING_PARAM'))
I get the expected result.
I am even able to create .NET classes from Visual Studio Server Explorer wizard for the user defined types.
However when I try to create import function from the Entity Framework model wizard I don't get a proper option to define the returned type.
Am I trying to do something not supported?
Import function doesn't behave the way you might expect with ODP.NET. It assumes that the first SYS_REFCURSOR it finds as an OUT parameter is the "return value" of the Entity Function.
Therefore, you will need to wrap your function with a stored procedure that places the nested table data in a REF CURSOR.
Then you need to learn about the required metadata in the config file for this REF CURSOR. In the online help for Oracle Developer Tools for Visual Studio, read the Entity Framework section for more information.
Here is a walkthrough that shows how to set up an Import Function:
https://apex.oracle.com/pls/apex/f?p=44785:24:106387346683725:::24:P24_CONTENT_ID,P24_PROD_SECTION_GRP_ID,P24_PREV_PAGE:10068,,24
Due to the complexity of all this, I don't advise using Imported Functions with non scalar Oracle Stored Functions or Procedures return values unless you absolutely have to.