How to declare a variable in denodo? - denodo

There is a question related to this topic but is not the same that I am going to ask, I need to do something similar as we do in SQL but this time in Denodo.
This is in SQL:
DECLARE #curr varchar (10);
SET #curr = 'USD;
SELECT
Country,
Currency
FROM
Currencies
WHERE
Currency = #curr;
I have tried something like this in Denodo
SELECT
Country,
Currency
FROM
Currencies
WHERE
Currency = GETVAR('curr', 'VARCHAR', 'USD');
But is not showing results. Does anyone know how can we do something similar to SQL variable declaration in Denodo?

The error is caused because of the wrong data type
You can use 'text' instead of using 'varchar'
This change will save your query :)
Here is a sample usage
select
*
from
storm_storm_t001l
where
werks = GETVAR('werks', 'text', '1331')
;

Use function GETVAR('variable_name', 'type', default_value) in your query.
Then declare it in the CONTEXT statement: CONTEXT('VAR variable_name' = literal)
For example
SELECT *
FROM (
SELECT 1 FROM DUAL()
UNION ALL
SELECT 2 FROM DUAL()
UNION ALL
SELECT 3 FROM DUAL()
)
WHERE field1 > GETVAR('a', 'int', 3)
ORDER BY field1
CONTEXT('VAR a' = 1)

Related

bigquery sql table function with string interpolation

I am trying to write a BigQuery SQL function / stored procedure / table function that accepts as input:
a INT64 filter for the WHERE clause,
a table name (STRING type) as fully qualified name e.g. project_id.dataset_name.table_name
The idea is to dynamically figure out the table name and provide a filter to slice the data to return as a table.
However if try to write a Table Function (TVF) and I use SET to start dynamically writing the SQL to execute, then I see this error:
Syntax error: Expected "(" or keyword SELECT or keyword WITH but got keyword SET at [4:5]
If I try to write a stored procedure, then it expects BEGIN and END and throws this error:
Syntax error: Expected keyword BEGIN or keyword LANGUAGE but got keyword AS at [3:1]
If I try to add those, then I get various validation errors basically because I need to remove the WITH using CTEs (Common Table Expression), and semicolons ; etc.
But what I am really trying to do is using a table function:
to combine some CTEs dynamically with those inputs above (e.g. the input table name),
to PIVOT that data,
to then eventually return a table as a result of a SELECT.
A bit like producing a View that could be used in other SQL queries, but without creating the view (because the slice of data can be decided dynamically with the other INT64 input filter).
Once I dynamically build the SQL string I would like to EXECUTE IMMEDIATE that SQL and provide a SELECT as a final step of the table function to return the "dynamic table".
The thing is that:
I don't know before runtime the name of this table.
But I have all these tables with the same structure, so the SQL should apply to all of them.
Is this possible at all?
This is the not-so-working SQL I am trying to work around. See what I am trying to inject with %s and num_days:
CREATE OR REPLACE TABLE FUNCTION `my_dataset.my_table_func_name`(num_days INT64, fqn_org_table STRING)
AS (
-- this SET breaks !!!
SET f_query = """
WITH report_cst_t AS (
SELECT
DATE(start) as day,
entity_id,
conn_sub_type,
FROM `%s` AS oa
CROSS JOIN UNNEST(oa.connection_sub_type) AS conn_sub_type
WHERE
DATE(start) > DATE_SUB(CURRENT_DATE(), INTERVAL num_days DAY)
AND oa.entity_id IN ('my-very-long-id')
ORDER BY 1, 2 ASC
),
cst AS (
SELECT * FROM
(SELECT day, entity_id, report_cst_t FROM report_cst_t)
PIVOT (COUNT(*) AS connection_sub_type FOR report_cst_t.conn_sub_type IN ('cat1', 'cat2','cat3' ))
)
""";
-- here I would like to EXECUTE IMMEDIATE !!!
SELECT
cst.day,
cst.entity_id,
cst.connection_sub_type_cat1 AS cst_cat1,
cst.connection_sub_type_cat2 AS cst_cat2,
cst.connection_sub_type_cat3 AS cst_cat3,
FROM cst
ORDER BY 1, 2 ASC
);
This might not be satisfying but since Procedural language or DDL are not allowed inside Table functions currently, one possible way around would be simply using PROCEDURE like below.
CREATE OR REPLACE PROCEDURE my_dataset.temp_procedure(filter_value INT64, table_name STRING)
BEGIN
EXECUTE IMMEDIATE FORMAT(CONCAT(
"SELECT year, COUNT(1) as record_count, ",
"FROM %s ",
"WHERE year = %d ",
"GROUP BY year ",
"; "
), table_name, filter_value);
END;
CALL my_dataset.temp_procedure(2002, 'bigquery-public-data.usa_names.usa_1910_current');

How to select specific column types in SQLite3?

PRAGMA table_info(myTable)
This query selects all the info in a table, for example: if there are 2 columns in a table then this query will select all the column names, column types e.t.c
I just want add one clause i.e I want to get info of specific columns that I define in the query.
Like this:
PRAGMA table_info(myTable) where columnNames = 'a' and columnNames = 'b' // this is wrong query but I just mentioned it to make my question more clear.
How can I do this?
You can pragma_table_info() in a query with a WHERE clause:
SELECT *
FROM pragma_table_info('myTable') -- note the single quotes
WHERE name IN ('a', 'b') -- equivalent: name = 'a' OR name = 'b'
See the demo.

Create dynamic SQL based on column names passed through a string

I need to find out rows that are present in table A and missing from table B (using LEFT JOIN) wherein table A and table B are two tables with same structure but within different schema.
But the query has to be constructed using Dynamic SQL and the columns that need to be used for performing JOIN are stored in a string. How to extract the column names from string and use them to dynamically construct below query :
Database is Azure SQL Server
eg :
DECLARE #ColNames NVARCHAR(150) = 'col1,col2'
Query to be constructed based on columns defined in ColNames :-
SELECT *
FROM Table A
Left Join
Table B
ON A.col1 = B.col1
AND A.col2 = B.col2
AND B.col1 IS NULL AND B.col2 IS NULL
If the number of columns in #ColNames is more then the SELECT statement needs to cater for all the column.
Without knowing the full context, try this:
DECLARE #ColNames NVARCHAR(150) = 'col1,col2'
DECLARE #JoinContion NVARCHAR(MAX) = ''
DECLARE #WhereCondition NVARCHAR(MAX) = ''
SELECT #JoinContion += CONCAT('[a].', QUOTENAME(Value), ' = ', '[b].', QUOTENAME(Value), (CASE WHEN LEAD(Value) OVER(ORDER BY Value) IS NOT NULL THEN ' AND ' ELSE '' END))
,#WhereCondition += CONCAT('[a].', QUOTENAME(Value), ' IS NULL', (CASE WHEN LEAD(Value) OVER(ORDER BY Value) IS NOT NULL THEN ' AND ' ELSE '' END))
FROM STRING_SPLIT(#ColNames,N',')
SELECT #JoinContion, #WhereCondition
String_Split: To split the input string into columns
Lead: to determine if we need the AND keyword when it's not the last row.
Be aware the NOT EXISTS is probably a better solution then LEFT JOIN

comparing values from a multi-value parameter to a dataset column in SSRS

I have a dataset created from a stored procedure by passing it a multi-value parameter. What I now need is to check whether all values from the parameter came back in a specific column of my result set or not, and if not, then display those values in the report.
So, for example, if I'm passing values 'a', 'b', 'c' and 'd' to my parameter, and if my dataset column only contains 'a' and 'd', then I need a way to display 'b' and 'c' on the report.
Thanks,
Pratik
First, you'll need a query that is supplying the values for your parameter. The query might look something like this:
select 'a' as ParamValue
union all
select 'b' as ParamValue
union all
select 'c' as ParamValue
union all
select 'd' as ParamValue
Set you parameter values to be populated by this query:
Now Add a table that can list your parameter values.
Next, you can check if each value exists in your main dataset using a Lookup function like this:
=IIf(IsNothing(Lookup(Fields!PARAMVALUE.Value,Fields!COLVALUE.Value,Fields!COLVALUE.Value, "MainDataSet")), True, False)
You can use this as a filter to just show the parameter values where this function doesn't return a value:
Can you change the stored procedure (or make a new one based on the old one for this report)? If so, then you could change from an INNER JOIN to an OUTER JOIN and get that result. For example, if your stored procedure showed how much clients were billed last month and looked like:
SELECT ClientName, SUM(BillAmount) AS TotalBilled
FROM Clients
INNER JOIN Bills ON Clients.ClientId = Bills.ClientId AND Bills.BillDate >= DateAdd(m, -1, GetDate())
WHERE ClientId IN #ClientIds
GROUP BY ClientName
ORDER BY ClientName
then this would exclude any clients not billed. If you change to an OUTER JOIN like so:
SELECT ClientName, SUM(BillAmount) AS TotalBilled
FROM Clients
LEFT OUTER JOIN Bills ON Clients.ClientId = Bills.ClientId AND Bills.BillDate >= DateAdd(m, -1, GetDate())
WHERE ClientId IN #ClientIds
GROUP BY ClientName
ORDER BY ClientName
then clients with no bills would still show with a Null amount for the amount billed

Find Sybase stored procedure in db given a text string that appears in the proc

How do I find a stored procedure in a Sybase database given a text string that appears somewhere in the proc? I want to see if any other proc in the db has similar logic to the one I'm looking at, and I think I have a pretty unique search string (literal)
Edit:
I'm using Sybase version 11.2
Two variations on Graeme's answer (So this also won't work on 11.2):
This lists the name of the sproc too, but will return multiple rows for each sproc if the text appears several times:
select object_name(id),* from syscomments
where texttype = 0 and text like '%whatever%'
This lists each sproc just once:
select distinct object_name(id) from syscomments
where texttype = 0 and text like '%whatever%'
In SQL Anywhere and Sybase IQ:
select * from SYS.SYSPROCEDURE where proc_defn like '%whatever%'
I'm not that familiar with ASE, but according to the docs (available from sybooks.sybase.com), it's something like:
select * from syscomments where texttype = 0 and text like '%whatever%'
Please remember, that text column in syscomments is varchar(255), so one big procedure can consist of many lines in syscomments, thus, the above selects will not find the procedure name if it has been splitted into 2 text rows in syscomments.
I suggest the following select, which will handle the above case:
declare #text varchar(100)
select #text = "%whatever%"
select distinct o.name object
from sysobjects o,
syscomments c
where o.id=c.id
and o.type='P'
and (c.text like #text
or exists(
select 1 from syscomments c2
where c.id=c2.id
and c.colid+1=c2.colid
and right(c.text,100)+ substring(c2.text, 1, 100) like #text
)
)
order by 1
-- kudos for this go to the creator of ASEisql
select * from sysobjects where
id in ( select distinct (id) from syscomments where text like '%SearchTerm%')
and xtype = 'P'
select distinct object_name(syscomments.id) 'SearchText', syscomments.id from syscomments ,sysobjects
where texttype = 0 and text like '%SearchText%' and syscomments.id=sysobjects.id and sysobjects.type='P'
Multiple rows are used to store text for database objects the value might be accross two rows. So the more accurate answer is:
select distinct object_name(sc1.id)
from syscomments sc1
left join syscomments sc2
on (sc2.id = sc1.id and
sc2.number = sc1.number and
sc2.colid2 = sc1.colid2 + ((sc1.colid + 1) / 32768) and
sc2.colid = (sc1.colid + 1) % 32768)
where
sc1.texttype = 0 and
sc2.texttype = 0 and
lower(sc1.text + sc2.text) like lower('%' || #textSearched || '%')

Resources