List of aggregate functions - mysql

Is there a way to fetch list of aggregate functions supported by a dbms using jdbc metadata or running any dbms specific query?

On SQL Server you can query XML which is in installation directory:
DECLARE #xml XML
SELECT #xml = x.y
FROM OPENROWSET( BULK 'C:\Program Files (x86)\Microsoft SQL Server\100\Tools\Binn\VSShell\Common7\IDE\SqlToolsData\1033\SQLCommonObjects.xml', SINGLE_BLOB ) x(y)
;WITH XMLNAMESPACES( 'http://tempuri.org/SqlCommonObjects.xsd' AS ns )
SELECT
Category.Name.value('ns:DisplayName[1]', 'VARCHAR(MAX)') [Category],
[Function].Name.value('ns:Name[1]', 'VARCHAR(MAX)') [Function],
[Function].Name.query('for $p in ns:Parameters/ns:Parameter return
concat($p/ns:Name[1],",")').value('.', 'VARCHAR(MAX)') Parameters
FROM #xml.nodes('//ns:Category[ns:DisplayName="Aggregate Functions"]')
AS Category(Name)
CROSS APPLY Category.Name.nodes('ns:Objects/ns:Function') [Function](Name)
Where after BULK statement you should give your folder(difference mainly is Program Files" and "Program_Files(x86)" and SQL server version (100 is 2008 in example)

Your post has multiple DB tags, and each has system catalogs and/or an information schema that would let you know the list of procedures. Which table/view to query will differ from a DB engine to the next, however... (For instance, in Postgres you'd join pg_proc and pg_aggregate, since information_schema.routines won't tell you which procs are aggregates.)
It is usually safe to assume that typical aggregate functions (sum(), count(), avg()...) exist in all database implementations.
The only exception I'm aware of is Postgres, which does not support any()/some() due to ambiguity in the syntax:
SELECT b1 = ANY((SELECT b2 FROM t2 ...)) FROM t1 ...;

There is nothing fullproof, since it is not part of the JDBC spec. If you don't know what database engine you are using at runtime, your best bet is to submit a test query to the database and check whether or not it failed before using any aggregate function that may not be supported.

Related

Common Table Expressions -- Using a Variable in the Predicate

I've written a common table expression to return hierarchical information and it seems to work without issue if I hard code a value into the WHERE statement. If I use a variable (even if the variable contains the same information as the hard coded value), I get the error The maximum recursion 100 has been exhausted before statement completion.
This is easier shown with a simple example (note, I haven't included the actual code for the CTE just to keep things clearer. If you think it's useful, I can certainly add it).
This Works
WITH Blder
AS
(-- CODE IS HERE )
SELECT
*
FROM Blder as b
WHERE b.PartNo = 'ABCDE';
This throws the Max Recursion Error
DECLARE #part CHAR(25);
SET #part = 'ABCDE'
WITH Blder
AS
(-- CODE IS HERE )
SELECT
*
FROM Blder as b
WHERE b.PartNo = #part;
Am I missing something silly? Or does the SQL engine handle hardcoded values and parameter values differently in this type of scenario?
Kindly put semicolon at the end of your variable assignment statement
SET #part ='ABCDE';
Your SELECT statement is written incorrectly: the SQL Server Query Optimizer is able to optimize away the potential cycle if fed the literal string, but not when it's fed a variable, which uses the plan that developed from the statistics.
SQL Server 2016 improved on the Query Optimizer, so if you could migrate your DB to SQL Server 2016 or newer, either with the DB compatibility level set to 130 or higher (for SQL Server 2016 and up), or have it kept at 100 (for SQL Server 2008) but with OPTION (USE HINT ('ENABLE_QUERY_OPTIMIZER_HOTFIXES')) added to the bottom of your SELECT statement, you should get the desired result without the max recursion error.
If you are stuck on SQL Server 2008, you could also add OPTION (RECOMPILE) to the bottom of your SELECT statement to create an ad hoc query plan that would be similar to the one that worked correctly.

How to invoke json_val function in db2 json?

I'm trying to index a particular value from stored DB2 nosql, for that I'm using json_val but I need to invoke UDF SYSTOOLS.BSON2JSON to the json_val and need to point the table from where I required data.
SELECT SYSTOOLS.BSON2JSON(CUSTOMERDATA)
FROM JSONPO
WHERE YEAR(JSON_VAL(CUSTOMERDATA,'PO.#orderDate', 'd')) = 2017;
The above query resulting in sql error -440 so I need to invoke the json_val. How would I invoke it? How would I write stored procedure for it?
In the year 2017, it should be called as SYSTOOLS.JSON_VAL if your database is enabled for JSON data. I see in your query, the schema name is missing.
In latest version of db2 as of today, your query should work. For more info, you can refer db2 documentation here: https://www.ibm.com/docs/en/db2/11.5?topic=functions-json-val

Deploying to hundreds of mysql databases [duplicate]

Is there any way to easily create a stored procedure on multiple MySQL databases at once? All the databases are on the same MySQL install.
Installing in all schemas
To get a list of the schemas, use show databases;. Combine this with -- use:
use schemaA;
-- use schemaB;
-- use schemaC;
create procedure ...
Manually iterate through the schemas, removing and uncommenting use clauses as you move on, checking that everything works out. In MySQL Workbench, Ctrl+Shift+Enter is your friend.
Installing routines in a subset of schemas
Normally you don't want to install the stored routine in all schemas on a server, but only in a subset --- often defined by the set of schemas which already have some specific stored routine installed. Then, as discussed on SO, you can use a query like this to get the names of the relevant schemas:
SELECT ROUTINE_SCHEMA FROM `information_schema`.`ROUTINES` where specific_name = 'MyRoutine';
Verification
After deploying routines, to verify the existence of them, you can use a query like this:
SELECT distinct
r1.ROUTINE_SCHEMA,
case when r2.specific_name is not null then '' else '####' end as RoutineName1,
case when r3.specific_name is not null then '' else '####' end as RoutineName2,
case when r4.specific_name is not null then '' else '####' end as RoutineName3
FROM
`information_schema`.`ROUTINES` as r1
LEFT JOIN (select * from `information_schema`.`ROUTINES` where specific_name = 'RoutineName1') as r2 on r1.routine_schema = r2.routine_schema
LEFT JOIN (select * from `information_schema`.`ROUTINES` where specific_name = 'RoutineName2') as r3 on r1.routine_schema = r3.routine_schema
LEFT JOIN (select * from `information_schema`.`ROUTINES` where specific_name = 'RoutineName3') as r4 on r1.routine_schema = r4.routine_schema
where
r1.specific_name = 'FilteringRoutineName';
This query will check whether RoutineName1, RoutineName2 and RoutineName3 exist in the database schemas on your server which have the routine FilteringRoutineName. If a routine is missing, it will be marked with ####.
Of course, this only checks for routine existence. To verify their implementation, you may need a database diff tool (such as MySQL Compare or similar).
Assuming you are using Linux, a simple BASH loop with an array of schema names will let you do this.
Save your procedure definition to a file (e.g. myproc.sql), then use the file as input to mysql in the loop. If you put your sign-in details in ~/.my.cnf you can also avoid having to put usernames and passwords on the cmdline.
for i in dbname1 dbname2 dbname3; do mysql ${i} < myproc.sql; done;
I would recommend doing a copy-paste and create the stored procedure in each database schema if they need to be available to that schema only. Otherwise I would follow the recommendation from 'Kelly Vista' and just refer to the stored procedure located in one of the schema's.

jTDS incorrectly reports data type info in result set metadata (for DATE columns, reports NVARCHAR)

Currently, the jTDS JDBC driver (1.2.5) against Microsoft SQL Server 2008 appears to incorrectly report the data type for DATE columns as NVARCHAR.
It probably behaves the same for both earlier versions of jTDS and SQL Server (2005, 2000)
Are there any workarounds for this that don't require switching to a different driver (for example Microsoft's own driver) or patching the jTDS driver?
Also I would like to avoid having to perform queries against the data dictionary (INFORMATION_SCHEMA.COLUMNS view, etc.) to look up the data type information (and possibly cross-referencing against the output of "exec sp_datatype_info" in order to retrieve the SQL data types)
A quick perusal of the jTDS outstanding bugs doesn't indicate whether this will be fixed or not.
An answer to this question: JDBC - JTDS bug ? For columns of type date and time(x) seems to indicate that this doesn't occur in SQL Server 2005.
Thanks in advance.
I found a solution with the condition
metaData.getColumnType(columnNumber) == 12
if this condition is satisfied, execute the query
SELECT System_Type_Id FROM Sys.Columns WHERE Name = [column name] AND Object_Id = (SELECT Object_Id FROM Sys.Tables WHERE Name = [table name])
for smalldatetime it will return 58
and for datetime it will return 61.

Install Stored Procedure on Multiple Databases

Is there any way to easily create a stored procedure on multiple MySQL databases at once? All the databases are on the same MySQL install.
Installing in all schemas
To get a list of the schemas, use show databases;. Combine this with -- use:
use schemaA;
-- use schemaB;
-- use schemaC;
create procedure ...
Manually iterate through the schemas, removing and uncommenting use clauses as you move on, checking that everything works out. In MySQL Workbench, Ctrl+Shift+Enter is your friend.
Installing routines in a subset of schemas
Normally you don't want to install the stored routine in all schemas on a server, but only in a subset --- often defined by the set of schemas which already have some specific stored routine installed. Then, as discussed on SO, you can use a query like this to get the names of the relevant schemas:
SELECT ROUTINE_SCHEMA FROM `information_schema`.`ROUTINES` where specific_name = 'MyRoutine';
Verification
After deploying routines, to verify the existence of them, you can use a query like this:
SELECT distinct
r1.ROUTINE_SCHEMA,
case when r2.specific_name is not null then '' else '####' end as RoutineName1,
case when r3.specific_name is not null then '' else '####' end as RoutineName2,
case when r4.specific_name is not null then '' else '####' end as RoutineName3
FROM
`information_schema`.`ROUTINES` as r1
LEFT JOIN (select * from `information_schema`.`ROUTINES` where specific_name = 'RoutineName1') as r2 on r1.routine_schema = r2.routine_schema
LEFT JOIN (select * from `information_schema`.`ROUTINES` where specific_name = 'RoutineName2') as r3 on r1.routine_schema = r3.routine_schema
LEFT JOIN (select * from `information_schema`.`ROUTINES` where specific_name = 'RoutineName3') as r4 on r1.routine_schema = r4.routine_schema
where
r1.specific_name = 'FilteringRoutineName';
This query will check whether RoutineName1, RoutineName2 and RoutineName3 exist in the database schemas on your server which have the routine FilteringRoutineName. If a routine is missing, it will be marked with ####.
Of course, this only checks for routine existence. To verify their implementation, you may need a database diff tool (such as MySQL Compare or similar).
Assuming you are using Linux, a simple BASH loop with an array of schema names will let you do this.
Save your procedure definition to a file (e.g. myproc.sql), then use the file as input to mysql in the loop. If you put your sign-in details in ~/.my.cnf you can also avoid having to put usernames and passwords on the cmdline.
for i in dbname1 dbname2 dbname3; do mysql ${i} < myproc.sql; done;
I would recommend doing a copy-paste and create the stored procedure in each database schema if they need to be available to that schema only. Otherwise I would follow the recommendation from 'Kelly Vista' and just refer to the stored procedure located in one of the schema's.