How to use variables in SQL queries on DataGrip (Exasol dialect)? - sql

Database: EXASOL
IDE: IntelliJ DataGrip
I am trying to declare variables in SQL and call them throughout the query.
This is the equivalent in Microsoft SQL Server:
DECLARE #var AS INT = 3
SELECT #var AS var
-- Use case example:
SELECT * FROM table1 WHERE column_value = #var
Is this possible in DataGrip and Exasol? I searched the documentation (General Script Language, Database Interaction) of Exasol where they describe the following:
a = 3
SELECT :a
However, this opens a console where I am asked to type the value of a. I don't want to type the values of variables every time I execute the code. I want to set a variable and use it on different parts of the query, just like any other high-level programming language.
I found two similar questions on JetBrains' forum (1, 2) but they are unanswered. Another one found on StackOverflow (url) just stated that the dialect is not supported on DataGrips.
Does anyone know how to solve this? Is it simply not supported? It would really increase productivity for me and my team.
Thank you in advance!

After spending some time, I found out that this is not possible. Instead Exasol allows LUA scripts that can run such calculations. Below you will find an example:
CREATE LUA SCRIPT "TEST" (p_country) RETURNS TABLE AS
local param_c = p_country
exit(
query(
[[
SELECT * FROM SCHEMA_NAME.TABLE_NAME
WHERE SK_COUNTRY = :local_c;
]]
,{local_c=param_c}
)
);
/
EXECUTE SCRIPT SCHEMA_NAME.TEST('DE');
In this example the keyword RETURNS TABLE outputs the table results from this query. The keyword exit() is similar to a print() method. And lastly, I don't know why but the function parameter needs to be assigned to a local variable, which then needs to be assigned to another variable in the query. This makes no sense to me, but I could not get it to work otherwise.
In my example I have the script parameter p_country which is assigned to the local parameter param_c which is then assigned to the query parameter local_c.
You can find the documentation under:
https://docs.exasol.com/database_concepts/scripting/general_script_language.htm?Highlight=for%20loop
https://docs.exasol.com/database_concepts/scripting/db_interaction.htm

Related

Oracle SQL Developer: possible to pass parameters to SQL script?

I have the following SQL script (all names replaced with metasyntactic variables):
DELETE FROM FOO
WHERE UPPER(BAR)=? AND UPPER(BAZ)=? AND UPPER(QUX)=? AND UPPER(QUUX)=? AND UPPER(CORGE)=?;
When I run it in SQL Developer, I get the following error, as expected: SQL Error: Missing IN or OUT parameter at index:: 1
Is there a way in SQL Developer to pass test parameters to these values (in this case, BAR, BAZ, QUX, QUUX, and CORGE) or do I have to manually replace the question marks? Thanks!
UPDATE: I've been looking on the internet to try to find the answer with no luck; none of the articles I found deal with the FOO=? syntax. I know that that is the proper syntax to access (and in this case, delete from) the database from a Java program, but I would like to test the SQL script before embedding it in the program.
A query that way is called a prepared statement. It is used as a way to send SQL statements from a program to the database.
First you have to prepare the prepared statement object and later you supply the parameters and finally execute the statement. When setting the parameters, you refer to each question mark in the order they apear in the statement. So in you case, BAR would be parameter 1 and CORGE will be parameter 5.
http://docs.oracle.com/javase/tutorial/jdbc/basics/prepared.html
For testing a query like this is quite useless in my experience. You could change the paramters to variables or even substitution variables if that is more convenient while testing.
http://docs.oracle.com/cd/B19306_01/server.102/b14357/ch5.htm#i1211130

Teradata SQL parameter syntax

Is there syntax which allows a parameter marker in the middle of a table name? For example, consider the queries
sel * from t?x
and
sel * from t?x_blah.
Both execute as
sel * from t1
if the user inputs 1. In the first query x = 1 and in the second query x_blah = 1. I would like to modify the second query to set x = 1 and execute as
sel * from t1_blah.
Is there a way to do this?
Thanks!
A question mark parameter marker can only be used for data values, not object names. So, the short answer is no.
Here's some info from Teradata:Clicky!
What's your client tool?
SQL Assistant supports parameters for object names, but there's no way to get the expected behavior (as you probably noticed).
The only solution might be using Dynamic SQL within a Stored Procedure.
A ? works in Teradata SQL Assistant. It will ask you to enter the parameter:
select ?x from ?y;
When you run it, SQL Assistant will ask you for the parameters x and y. If you put 10 instances of ?x in your code, SQL Assistant will only ask for x once.

Calling a stored function (that returns an array of a user-defined type) in oracle across a database link

Normally, I call my function like so:
SELECT *
FROM TABLE(
package_name.function(parameters)
)
I'm trying to call this function across a database link. My intuition is that the following is the correct syntax, but I haven't gotten it to work:
SELECT *
FROM TABLE(
package_name.function#DBLINK(parameters)
)
> ORA-00904: "PACKAGE_NAME"."FUNCTION": invalid identifier
I've tried moving around the database link to no effect. I've tried putting it after the parameter list, after the last parenthesis, after the package name...I've also tried all of the above permutations including the schema name before the package name. I'm running out of ideas.
This is oracle 10g. I'm suspicious that the issue may be that the return type of the function is not defined in the schema in which I'm calling it, but I feel like I should be getting a different error if that were the case.
Thanks for your help!
What you're trying is the correct syntax as far as I know, but in any case it would not work due to the return type being user-defined, as you suspect.
Here's an example with a built-in pipelined function. Calling it locally works, of course:
SELECT * FROM TABLE(dbms_xplan.display_cursor('a',1,'ALL'));
Returns:
SQL_ID: a, child number: 1 cannot be found
Calling it over a database link:
SELECT * FROM TABLE(dbms_xplan.display_cursor#core('a',1,'ALL'));
fails with this error:
ORA-30626: function/procedure parameters of remote object types are not supported
Possibly you are getting the ORA-904 because the link goes to a specific schema that does not have access to the package. But in any case, this won't work, even if you define an identical type with the same name in your local schema, because they're still not the same type from Oracle's point of view.
You can of course query a view remotely, so if there is a well-defined set of possible parameters, you could create one view for each parameter combination and then query that, e.g.:
CREATE VIEW display_cursor_a_1_all AS
SELECT * FROM TABLE(dbms_xplan.display_cursor('a',1,'ALL'))
;
If the range of possible parameter values is too large, you could create a procedure that creates the needed view dynamically given any set of parameters. Then you have a two-step process every time you want to execute the query:
EXECUTE package.create_view#remote(parameters)
SELECT * FROM created_view#remote;
You have to then think about whether multiple sessions might call this in parallel and if so how to prevent them from stepping on each other.

how to declare global variable in sql

I would like create a GLOBAL VARIABLE in a Sql script.
For my understanding using DECLARE I will be able to create just LOCAL variable.
Any idea how to create theem?
thanks
Assuming MS SQL Server, and assuming the MS definition of 'Global Variable' you cannot. If you need a variable to be accessable across multiple stored procedures, or ad-hoc queries, you will need some other way to hold the data: say a table which holds the variable for you.
Note: the hyperlink does not go to Microsoft, I could not find a copy of Microsoft's specific definition, but the website linked came close enough for this discussion.
Why don't you just create a table do hold the system wide data you need?
You can make a scalar function that returns hard code value.
Example:
CREATE FUNCTION [dbo].[APPID]()
RETURNS INT BEGIN
RETURN 1
To use:
SELECT [dbo].[APPID]()
or
SELECT * FROM ApplicationAccount WHERE AppID = dbo.APPID()

Display DataType and Size of Column from SQL Server Query Results at Runtime

Is there a way to run a query and then have SQL Server management studio or sqlcmd or something simply display the datatype and size of each column as it was received.
Seems like this information must be present for the transmission of the data to occur between the server and the client. It would be very helpful to me if it could be displayed.
A little background:
The reason I ask is because I must interface with countless legacy stored procedures with anywhere from 50 to 5000+ lines of code each. I do not want to have to try and follow the cryptic logic flow in and out of temp tables, into other procedures, into string concatenated eval statement and so on. I wish to maintain no knowledge of the implementation, simply what to expect when they work. Unfortunately following the logic flow seems to be the only way to figure out what exactly is being returned without trying to infer what the actual types of the data string representations om management studio studio or from the native type in .net for example.
To clarify: I am not asking about how to tell the types of a table or something static like that. I'm pretty sure something like sp_help will not help me. I am asking how to tell what the sql server types (ie varchar(25), int...) are of what I have been given. Additionally, changing the implementation of the sprocs is not possible so please consider that in your solutions. I am really hoping there is a command I have missed somewhere. Much appreciation to all.
Update
I guess what I am really asking is how to get the schema of the result set when the result set originates from a query using a temp table. I understand this to be impossible but don't find much sense with that conclusion because the data is being transmitted after all. Here is an example of a stored procedure that would cause a problem.
CREATE PROCEDURE [dbo].[IReturnATempTable]
AS
Create table #TempTable
(
MyMysteryColumn char(50)
)
INSERT #TempTable (
MyMysteryColumn
) VALUES (
'Do you know me?' )
select TOP 50 * FROM #TempTable
What will you do about stored procedures which return different result sets based on their parameters?
In any case, you can configure a SqlDataAdapter.SelectCommand, along with the necessary parameters, then call the FillSchema method. Assuming that the schema can be determined, you'll get a DataTable configured with correct column names and types, and some constraints.
A bit of a long shot, try messing around with SET FMTONLY ON (or off). According to BOL, this "Returns only metadata to the client. Can be used to test the format of the response without actually running the query." I suspect that this will inlcude what you're looking for, as BCP uses this. (I stumbled across this setting when debugging some very oddball BCP problems.)
Could you append another select to your procedure?
If so you might be able to do it by using the sql_variant_property function.
Declare #Param Int
Set #Param = 30
Select sql_variant_property(#Param, 'BaseType')
Select sql_variant_property(#Param, 'Precision')
Select sql_variant_property(#Param, 'Scale')
I posted that on this question.
I am asking how to tell what the sql
server types (ie varchar(25), int...)
are of what I have been given
You could then print out the type, precision (i.e. 25 if its VarChar(25)), and the scale of the parameter.
Hope that helps... :)
If you are not limited to T-SQL, and obviously you don't mind running the SPs (because SET FMTONLY ON isn't fully reliable), you definitely CAN call the SPs from, say C#, using a SqlDataReader. Then inspect the SqlDataReader to get the columns and the data types. You might also have multiple result sets, you you can also go to the next result set easily from this environment.
This code should fix you up. It returns a schema only dataset with no records. You can use this Dataset to query the columns' DataType and any other metadata. Later, if you wish, you can populate the DataSet with records by creating a SqlDataAdapter and calling it's Fill method (IDataAdapter.Fill).
private static DataSet FillSchema(SqlConnection conn)
{
DataSet ds = new DataSet();
using (SqlCommand formatCommand = new SqlCommand("SET FMTONLY ON;", conn))
{
formatCommand.ExecuteNonQuery();
SqlDataAdapter formatAdapter = new SqlDataAdapter(formatCommand);
formatAdapter.FillSchema(ds, SchemaType.Source);
formatCommand.CommandText = "SET FMTONLY OFF;";
formatCommand.ExecuteNonQuery();
formatAdapter.Dispose();
}
return ds;
}
I know this is an old question, I found it through a link from SqlDataAdapter.FillSchema with stored procedure that has temporary table. Unfortunately, neither question had an accepted answer, and none of the proposed answers were able to resolve my issue.
For the sake of brevity, if you are using SQL Server 2012 or later, using the following built-in functions will work in most situations:
sys.dm_exec_describe_first_result_set
sys.dm_exec_describe_first_result_set_for_object
However, there are some cases in which these functions will not provide any useful output. In my case, the problem was more similar to the question linked above and therefore, I believe the solution is more appropriately answered under that question. My answer can be found here.