oracle to sql sever query translation - sql-server

Can someone help me to translate the below Oracle query to SQL SERVER syntax ?
with cte as(
select to_date('05-05-2022','mm-dd-yyyy') as eff_dt,
to_date('12-31-2022', 'mm-dd-yyyy') as exp_dt from dual
)
select eff,exp,round(months_between(exp,eff)) from(
select case when level = 1 then eff_dt
else add_months(trunc(eff_dt,'Y'),12*(level-1)) end as eff,
last_day(add_months(trunc(eff_dt,'Y'),12*level-1)) as exp
from
cte connect by level<=extract(year from exp_dt)-extract(year from eff_dt)+1)
;

Learn standard SQL language. MS SQL Server use standard SQL while Oracle has always wanted to go on its own dialect, despite the fact that Jim Melton, the technical mentor of Oracle was the reporter of the standard ISO SQL !
Well in any good book, you will find that CAST is the normative function to CAST... and CTE (Common Table Expression) is the normative construction to write recursive queries.
On this topic, you can use the paper I wrote many years ago : "Recursive Queries in SQL:1999 and SQL Server 2005"

Related

Convert Oracle SQL query to Azure SQL query

I have a pretty long Oracle SQL query that needs to be compatible for Azure SQL. I am new to both database types. Here is query:
MERGE INTO studies
USING dual
ON (study_id = :study_id)
WHEN NOT MATCHED THEN
INSERT (study_id, study_date)
VALUES (:study_id, :study_date)
I am not sure USING dual would work. I read some solution saying that USING dual is not necessary in SQL Server.
I really appreciate if you can explain what this query means and how I can translate this for Azure SQL query.
This Oracle merge query has just a WHEN NOT MATCHED clause and no WHEN MATCHED, so basically that's insert and not exists:
insert into studies(study_id, study_date)
select x.*
from (values(#study_id, #study_date)) as x(study_id, study_date)
where not exists (select 1 from studies s1 where s1.study_id = x.study_id)
This is logically equivalent to the original Oracle query.
As for your original question: SQL Server does supports its own flavor or merge statement, whose syntax is different than Oracle. You would rewrite the Oracle merge as:
merge studies as s
using (values(#study_id, #study_date)) as x(study_id, study_date)
on (s.study_id = x.study_id)
when not matched
then insert (study_id, study_date) values(x.study_id, x.study_date)

Semantic search results in SQL Server does not return more than 10 rows

I have set up and enabled semantic search successfully by following this tutorial by Microsoft in SQL Server 2017 Development Edition. The semantic search is enabled on a table nvarchar(max) field which retains English plain text to search them semantically. The table has 900+ rows but when I run the following SQL statement I do not receive more than 10 rows! Why am I seeing this behavior and what should I do to get more rows in the result of the statement?
declare #idToCompare int = 1044
SELECT TOP(50) KEY_TBL.matched_document_key AS MatchId , score
FROM SEMANTICSIMILARITYTABLE
(
MySemanticTable,
ContentToSearch,
#idToCompare
) AS KEY_TBL
ORDER BY KEY_TBL.score DESC
Turns out that this is an old issue that has never been addressed. This feature of SQL Server does not seem to worth utilizing unless there is a solution for that. Not sure why Microsoft introduced this feature!
https://social.msdn.microsoft.com/Forums/sqlserver/en-US/d9bdd8d5-dec4-4076-bcb8-692f1d509c74/semanticsimilaritytable-sql2012-1102100-why-pull-max-of-only-10-results?forum=sqldatabaseengine

Need Help Converting Oracle Query to SQL Server

Several weeks ago I made a post to get help with converting a comma delimited list of values into a format that it could be used as part of an IN clause in Oracle. Here is a link to the post.
Oracle invalid number in clause
The answer was to split up the list into an individual row for each value. Here's the answer that I ended up using.
SELECT trim(regexp_substr(str, '[^,]+', 1, LEVEL)) str
FROM ( SELECT '1,2,3,4' str FROM dual )
CONNECT BY instr(str, ',', 1, LEVEL - 1) > 0
Is there a way that I can do something similar in SQL Server without having to create a custom function? I noticed that there's a STRING_SPLIT function, but I don't seem to have access to that on this SQL Server.
Any advice you might have would be greatly appreciated. I've been trying to take a stab at this for the majority of the day.
String_split function is available in MS SQL Server starting from version 2016. If you use older version you can write a few lines of code which do the same.
declare #str varchar(100)='1,2,3,4' --initial string
;with cte as (--build xml from the string
select cast('<s>'+replace(#str,',','</s><s>')+'</s>' as xml) x
)
--receive rows
select t.v.value('.[1]','int') value
from cte cross apply cte.x.nodes('s') t(v)

Microsoft SQL Server: How to improve the performance of a dumb query?

I have been asked to help with performance issue of a SQL server installation. I am not a SQL Server expert, but I decided to take a look. We are using a closed source application that appears to work OK. However after a SQL Server upgrade from 2000 to 2005, application performance has reportedly suffered considerably. I ran SQL profiler and caught the following query (field names changed to protect the innocent) taking about 30 seconds to run. My first thought was that I should optimize the query. But that is not possible, given that the application is closed source and the vendor is not helpful. So I am left, trying to figure out how to make this query run fast without changing it. It is also not clear to me how this query ran faster on the older SQL server 2000 product. Perhaps there was some sort of performance tuning applied to on that instance that did not carry over or does not work on the new SQL server. DBCC PINTABLE comes to mind.
Anyway, here is the offending query:
select min(row_id) from Table1 where calendar_id = 'Test1'
and exists
(select id from Table1 where calendar_id = 'Test1' and
DATEDIFF(day, '12/30/2010 09:21', start_datetime) = 0
)
and exists
(select id from Table1 where calendar_id = 'Test1' and
DATEDIFF(day, end_datetime, '01/17/2011 09:03') = 0
);
Table1 has about 6200 entries and looks like this. I have tried creating various indices to no effect.
id calendar_id start_datetime end_datetime
int, primary key varchar(10) datetime datetime
1 Test1 2005-01-01... 2005-01-01...
2 Test1 2005-01-02... 2005-01-02...
3 Test1 2005-01-03... 2005-01-03...
...
I would be very grateful if somebody could help resolve this mystery.
Thanks in advance.
The one thing that should help is a covering index on calendar_id:
create index <indexname>
on table (calendar_id, id)
include (start_datetime, end_datetime);
This will satisfy the calendar_id = 'Test1' predicates, the min(row_id) sort and will provide the material to evaluate the non-SARG-able DATEFIFF predicates. If there are no other columns in the table, then this is probably the clustered index you need and the id primary key should be a non-clustered one.
Make sure the indexes made the conversion. Then update statistics.
Check the differences between the execution plan on the old sql server and the new one. http://www.sql-server-performance.com/tips/query_execution_plan_analysis_p1.aspx
About the other only thing you can do beyond Remus Rusanu's index suggestion, is to upgrade to the Enterprise edition which has a more advanced scan feature (on both SQL Server 2005 and 2008 Enterprise Edition) which allows multiple tasks to share full table scans.
Beyond that, I do not think there is anything you can do if you cannot change the query. The reason is that the query is doing a comparison against a function result in the Where clause. That means it will force SQL Server to do a table scan on Table1 each time it is executed.
Reading Pages (more info about Advanced Scanning)

What is the purpose of "::" in T-SQL

In (non-English) book on T-SQL (SQL Server 2005) I read about:
SELECT * FROM ::fn_helpcollations()
Though, execution of it without "::"
SELECT * FROM fn_helpcollations()
In my SQL Server 2008 R2 gives exactly the same result.
What does "::" mean in T-SQL?
From MSDN:
However, when you call SQL Server
built-in functions that return a
table, you must add the prefix :: to
the name of the function:
SELECT * FROM ::fn_helpcollations()
Looks like you can omit the :: in SQL Server 2005 and 2008. The :: syntax will be supported for backward compatibility.

Resources