Jooq with SQL Server How to select top N results - sql-server

In our project we are using two databases, one postgres and one mssql. We are using Jooq in order to query these DBs and with postgres everything was pretty straight forward!
But with mssql we are facing some troubles. The task is to select the top 10 values and let's say that we have the following java code:
DSL.using(conn)
.select(USE_CASE.asterisk())
.from(USE_CASE)
.where(USE_CASE.RECORD_ACTIVE.eq(true))
.orderBy(USE_CASE.CREATED_ON.desc())
.limit(10)
.offset(0)
.fetch(new UseCaseMapper()))
This works like a charm with postgres but on mssql we get the following error:
Execution exception[[CompletionException: org.jooq.exception.DataAccessException:
SQL [select "park"."dbo"."use_case".* from "park"."dbo"."use_case" where
"park"."dbo"."use_case"."record_active" = ?
order by "park"."dbo"."use_case"."created_on" desc limit ?];
Incorrect syntax near 'limit'.]]
I know that for mssql the equivalent query would be something like,
select top 10 *
from use_case
where record_active = true
order by created_on desc;
How can I change my java code to get the limit records in mssql?

Correct SQLDialect
The exception message hints at the fact that you're still using the PostgreSQL (or some other non-SQL Server) dialect as your catalogs/schemas/tables/columns are quoted using "double_quotes", instead of [brackets].
Just use SQLDialect.SQLSERVER instead, when running your query on SQL Server. The LIMIT 10 syntax will then be correctly translated to TOP 10.
jOOQ Professional Edition vs jOOQ Open Source Edition
From our posted error messages, it is not quite clear how you really configured your jOOQ integration, but if you're using DSL.using(Connection) without explicitly specifying the SQLDialect, and jOOQ doesn't correctly "guess" the appropriate SQLDialect, this can mostly be because of one of two reasons:
You're using some non-standard JDBC URL, which jOOQ doesn't recognise. It thus uses SQLDialect.DEFAULT, instead, which produces the wrong SQL syntax for your.
You're using the jOOQ Open Source Edition (Maven groupId org.jooq) instead of the jOOQ Professional Edition (Maven groupId org.jooq.pro, to be installed manually, as it is not distributed via Maven Central), which would also lead to jOOQ using SQLDialect.DEFAULT.
Notice: this can also happen by accident, e.g. as a transitive dependency that is being pulled in via Spring Boot or some other framework that already depends on the jOOQ Open Source Edition. In that case, you have to make sure to exclude that transitive dependency from ending up on your classpath. In Maven, you can display all your dependencies using mvn dependency:tree

Related

NULL Reference Exception when generating DACPAC with particular Scalar UDF

I have a SQL Server 2017 database with a particular UDF that is giving me an error when trying to export a dacpac either via SSMS or sqlpackage. VisualStudio also throws the error when working in ssdt. The function works, and no issues there. included here is a dumbed down version of the function that has the same issues. You can create an empty database, add the function, and dacpac extract will fail. I understand there are poor design choices here, but this is just an example of the script, that still reproduces the error.
Function:
CREATE FUNCTION [dbo].[testFunction]
(
#string varchar(max)
)
RETURNS bit
AS
BEGIN
DECLARE #Valid BIT = CASE WHEN EXISTS (
SELECT *
FROM STRING_SPLIT(#string, ',') s
OUTER APPLY (select LEN(s.value) AS l) AS l
)
THEN 0 ELSE 1 END
RETURN #Valid
END
It literally just takes a comma separated string, splits it, does an outer apply to generate a length(I know, stupid IRL, but demo).
However, when attempting to extract a dacpac it gives error "Object reference not set to an instance of an object."
If I change the select * to select s.value, or select 1, then voila, dacpac generates and visual studio doesn't crash.
Anyone have any ideas as to why the select * in the above code would cause the dacpac to fail? We're evaluating using ssdt for source control, but random stuff like the above doesn't give me good feelings about using it, when it apparently is doing more code validation than the sql engine itself.
Environments:
SQL Server 2017 Standard
VS 2019 community with SSDT installed
SQLPackage Build 15.0.4826.1
I bet you are affected by following bug in SSDT:
SSDT failing to compile if STRING_SPLIT is used
It should be resolved few years ago, please check if you are using DACFX runtime 17.0.1 or newer
If you are using the VS function Extract Data-tier Application, you can uncheck Verify Extraction. I had to do this when using a dacpac to restore an Azure SQL DB Managed Instance database that had views referencing another database to an on-premise server. Otherwise it would appear to create a valid multi-gigabyte dacpac that could not be deployed on-premise with the same error you are getting.

Spring Pageable implementation on SQL Server 2008 - Offset clause

I am trying implement a paging and sorting repository with a #Query annotation. The query is simple enough:
SELECT DISTINCT(B.batch), B.scanDate, COUNT(B.batchReferenceNumber) as TransactionCount FROM Batch B
My database is SQL Server. The query that is getting generated is:
select
distinct batch0_.BatchNumber as col_0_0_,
count(batch0_.BatchNumber) as col_8_0_
from
BATCH batch0_
order by
batch0_.BatchNumber asc offset ? rows fetch next ? rows only
I get an error: Incorrect syntax near 'offset'.
The reason is "Offset" was not introduced until SQL Server 2012.
Is there any way around this? Or do I need to implement my own repository versus using the interface?
The SQL for the offset/limit clause is generated by your JPA provider.
You might be able to fix this by configuring the correct SqlDialect or if no such dialect is available you may raise an issue with that project.

Spring JDBC call for SQL Server function returning incorrect data

At first it looks like a silly question from a fairly new person, however my observations are very very strange. It may be difficult to answer because of unavailability of data and complete code. I'm looking for people who have faced similar issues and solution if possible.
Java and SQL codes:
I have a SQL Query which looks like below as java String for jdbcTemplate:
SELECT patientid, visitid, visitid1, visitid2, admitdate1, admitdate2, dischargedate1, dischargedate2, transfertype, sourcesystemuniqueidentifier FROM fn_XXXX_2017(?,?)
Here fn_XXXX_2017 is a SQL Server function that accepts two parameters of type BIGINT and definition is as below:
CREATE function [dbo].[fn_XXXX_2017]
( #id1 BIGINT ,#id2 BIGINT )
RETURNS TABLE
as
return
(
-- really big joins and unions
)
Spring jdbc call from java is as below:
long startRowNum = 111;
long endRowNum = 111;
List<Pojo> queryResult = this.jdbcTemplate.query(sqlQuery, new Object[]{startRowNum, endRowNum}, new MapperForPojo());
Observations and Cases:
When i execute the SQL Query directly into SQL Server Management Studio I get below results
Now we come to java to see the concern
Case 1 (Which works correct)
we use SQL Query for jdbcTemplate as:
SELECT patientid, visitid, visitid1, visitid2, admitdate1, admitdate2, dischargedate1, dischargedate2, transfertype, sourcesystemuniqueidentifier FROM fn_XXXX_2017(?,?)
Please notice there is no space in (?,?)
Case 2 (Which gives incorrect result)
we use SQL Query for jdbcTemplate as:
SELECT patientid, visitid, visitid1, visitid2, admitdate1, admitdate2, dischargedate1, dischargedate2, transfertype, sourcesystemuniqueidentifier FROM fn_XXXX_2017(?, ?)
Please notice the space before second question mark as (?,[space here]?)
In case two (Which doesn't work) i see data in eclipse as below:
This works unreliably when we add/remove spaces from the SQL Query String in java.
Tried below things to find the reason:
Looked into SQL Server profiler to make sure parameter values and
query is correct (Found it to be correct)
Debugged Spring java
Mappers to check if values are set correct (found it to be correct)
Debugged sqljdbc jar's by enabling
com.microsoft.sqlserver.jdbc.level=FINEST. (Even here i see that
values are not correct in the generated console logs)
this.jdbcTemplate.queryForList(query). here i hardcoded the
parameter values and found that it returns correct data.
Tried using latest version of microsofts sql jdbc driver sqljdbc42.jar
Confusion and question:
What may be wrong that this.jdbcTemplate.query(query, new Object[]{param1, param2}, Mapper()) version of jdbcTemplate is returning correct data only when i make removed spaces from sql query (just before last ? for parameter)?
Version information
Java Version:
java version "1.8.0_92"
Java(TM) SE Runtime Environment (build 1.8.0_92-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.92-b14, mixed mode)
SQL Server Version:
Microsoft SQL Server 2012 - 11.0.2100.60 (X64)
Feb 10 2012 19:39:15
Copyright (c) Microsoft Corporation
Developer Edition (64-bit) on Windows NT 6.2 (Build 9200: )
SQL JDBC jar: sqljdbc4-42.jar
Eclipse version: Neon and Mars
OS: Windows 10
Spring version 4.1.0.RELEASE

Oracle Database 12 c , SQL Server Translator Is not Translating query

I have installed SQLServer Translators as oracle document require to use 12 c jdbc jar so i replace this jar with jdbc jar.
I have created transport and created profile using sqldeveloper. I have followed steps given in oracle documentation
https://docs.oracle.com/database/121/DRDAA/sql_transl_install.htm#DRDAA29457
Now after completing installation my sqlserver profile has following parameters
Profile_name SQLSERVER_PROFILE
Translator "MON422_QA"."SQLSERVER_TSQL_TRANSLATOR"
Foreign_SQL_syntax True
Translate_new_sql True
Raise_translation_error false
Log_translationerro flase
Trace_translation false
I have installed for migration user and now when I am trying to use for different user I have given execute grant to target user.
But I am unable to translate sql query
Select top 1 * from dual;
Translator is not working as expected. If any additional information is required please let me know I will add the information.
EDIT Query I am trying to run
Select cast ( 5 to NVARCHAR2(50)) from dual;
Should be translated to
SELECT TO_CHAR(5) FROM DUAL:
But it says query terminated undesired parenthesis after NVARCHAR2;
We can see translated queries using sqldeveloper for translator profile being used. But my queries are not being translated at all.
Reference For Translator FrameWork
https://docs.oracle.com/database/121/DRDAA/sql_transl_install.htm#DRDAA29148
The SQL Server translator assumes it is receiving T-SQL or a SQL Server SQL statement in order to translate it.
If you want to use the translation framework to translate an oracle statement to another version of an oracle statement - you can totally do that. But you do not involve the SQL Server translator.
You simply add an entry in your translation profile, a 'template' of the SQL you want translated, and you also provide what you want to come out the other end.
Kerry wrote a very nice blog post demonstrating that here.

Using nvarchar cfsqltype in coldfusion with jtds jdbc

Firstly, my cconfig is:
Language: ColdFusion 10(and installed update 11)
DB is MS SQL Server 2012
Using the jtds jdbc(tried versions 1.2.6, 1.2.8 and 1.3.0)
I'm currently having a problem running queries where I use cfqueryparam with a cfsqltype of cf_sql_nvarchar. The problem is the page just hangs. If I look at the application log of ColdFusion, I see the error of:
"net.sourceforge.jtds.jdbc.JtdsPreparedStatement.setNString(ILjava/lang/String;)V The specific sequence of files included or processed is:" followed by the test filename.
I'm running a very basic select query on a nvarchar column, but the page doesn't load and that error is logged.
I know it's gotta be something to do with the jtds jdbc as if I connect through the regular sql driver it'll work perfectly.
So did anybody experience this before? If so, what was your resolution?
Thanks
I did a quick search and the results suggest jtds does not support setNString(). I checked the driver source for 1.3.1, and as mentioned in the comments here the method is not implemented:
"..while getNString is implemented the code just consists of // TODO
Auto-generated method stub and throw new AbstractMethodError();.."
So it sounds like you may need to use cf_sql_varchar, combined with the "String Format" setting, like in previous versions. Obviously, the other option is to use a different driver (one that does support setNString(), such as Adobe's driver or the MS SQL Server driver).
Try using cf_sql_varchar. cf_sql_nvarchar is not a valid option according to the Documentation and you should use cf_sql_varchar

Resources