Convert Oracle SQL query to Azure SQL query - sql-server

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)

Related

Passing SubQuery into OpenQuery with AS400 Linked Server

I have a Linked Server to the AS400 here. I'm trying to pull data from a field, but it is pulling over a million records when I only need about 20k.
I have a list of IDs that I need, and I'm trying to figure out how to pass that list into the OpenQuery.
Here is my OpenQuery:
SELECT * FROM OPENQUERY(AS400, '
SELECT
IMITNO, IMITD1, IMITD2, IMMFNO, IMBMTP, IMDSCO
FROM AS400.APLUS2FLE.ITMST
WHERE IMDSCO != ''Y''
')
I want to add WHERE IMITNO IN (SELECT item_id FROM as400_item_scope) but the as400_item_scope table is on the SQL machine, not the AS400. I looked at several examples and I can pass in a single variable, but I don't understand how to pass in a list/query like this.
I'm using latest SSMS, but SQL Server Version is 2008
You can't as far as I know...
Two options..
Insert the results of SELECT item_id FROM as400_item_scope into a (temporary?) table on the IBM i and then reference that table in your openquery.
build a comma delimited string with from the results of SELECT item_id FROM as400_item_scope and include that in your openquery string.
Depending on how many records are returned, you might run into issues with statement size trying to use option #2. Db2 for IBM i supports SQL statement of up to 2,097,152 bytes...

ORACLE to MSSQL using SSMS Import Wizard with Query to Update Rows

I have a situation which prevent me of updating rows in a table in MSSQL getting the data from ORACLE. I can INSERT fine from ORACLE to MS SQL using a SELECT statement like:
SELECT XRECORDACTIVATIONDATE, XRECORDCUTOFFDATE, XRECORDREVIEWDATE,
XRECORDFILINGDATE, XNOLATESTREVISIONDATE, XNEWREVISIONDATE, XDATERECEIVEDDOC,
XINACTIVEDATE, DCREATEDATE, DINDATE, DRELEASEDATE, DLASTMODIFIEDDATE
FROM STELLENT.V_EXPORT_TO_MSSQL V
But when I try to update the rows based on an unique ID using:
UPDATE D
SET D.XRECORDACTIVATIONDATE = V.XRECORDACTIVATIONDATE
FROM DBO.DOCUMENT D
INNER JOIN STELLENT."V_EXPORT_TO_MSSQL" V ON D.DID = V.DID
I get the following error:
ORA-00933: SQL command not properly ended
(System.Data.OracleClient)
DBO.DOCUMENT is a MSSQL table.
STELLENT.V_EXPORT_TO_MSSQL is a View in ORACLE
I might be writing wrong the query I will appreciate some help. thank you.
Lukasz is correct - a select statement is a lot different from an insert statement.
The ORA-00933 error means your query is not formed properly. This is because in Oracle, the database expects queries to follow a certain format/standard. Typically, queries within Oracle will have a form of SELECT [columns] FROM [tables] WHERE [conditions]. This can vary - for example if you wanted to select all data from a table, that query might look like "SELECT * FROM [table];" and the WHERE clause can be omitted because you do not need to define a condition for the database to return all rows. While queries can vary in form, in general, they will follow some type of format.
You are receiving this error because your query does not conform to the expected form, and it is because you have an INNER JOIN that directly follows your FROM clause. To fix this, I would recommend creating a query that you use to select the records you want to update, and then using that select statement to form your update statement by replacing the "SELECT" with "UPDATE".
For more on SQL Standards and how to format your queries, I would recommend taking a look at Oracle documentation. https://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_1001.htm#SQLRF52344

IBM i (AS400) to SQL Server table join syntax

I am using Excel Connection to query customer contracts from DB2 for IBM i (AS400) through SQL Server connection and trying to join a SQL Server table to determine contract expiration date and sales team responsibility.
The AS400 query operates but I continue to receive an error on joining the SQL Server table ACCOUNT.dbo.CUSTOMER but can't find reference to alternate syntax on the join.
[select *
from openquery(
bpcsrpt_new,'
select s.SCID, s.SVER, s.CONTEXP, a.ACCTNAME, a.SALESTEAM
from AS400table1.contract c, AS400table1.subcontract s, ACCOUNT.dbo.CUSTOMER a
where c.cid=''Active''
and c.cid=s.scid
and c.cver=s.sver
and c.cid=a.acid')]
That's not going to work. When you use openquery, the statement gets sent to the remote machine. Obviously, ACCOUNT.dbo.CUSTOMER is not on the remote IBM i (aka AS400) machine.
You could use 4 part naming in the query directly
select s.SCID, s.SVER, s.CONTEXP, a.ACCTNAME, a.SALESTEAM
from IBMILNKNAM.IBMIDBNAM.IBMILIBNAM.contract c
, IBMILNKNAM.IBMIDBNAM.IBMILIBNAM.subcontract s
, ACCOUNT.dbo.CUSTOMER a
where c.cid='Active'
and c.cid=s.scid
and c.cver=s.sver
and c.cid=a.acid
Note however, the SQL Server will pull back the complete contract and subcontract tables to do the join locally.
Openquery is a better option if you're only interested in a few rows of a large table on the IBM i. If I recall correctly, something like so: (not tested)
select *
from (select * from Openquery(IBMIKNKNAM, 'select s.SCID, s.SVER, s.CONTEXP
from contract c
join subcontract s
on c.cid=s.scid
and c.cver=s.sver
where c.cid=''Active'')) as rmt
join ACCOUNT.dbo.CUSTOMER a on a.acid = rmt.cid

Run query on sql server through teradata and store result in teradata

I have one table in SQL server and 5 tables in Teradata.I want to join those 5 table in teradata with sql server table and store result in Teradata table.
I have sql server name but i dont know how to simultaneously run a query both on sql server and teradata.
i want to do this:
sql server table query
Select distinct store
from store_Desc
teradata tables:
select cmp_id,state,sde
from xyz
where store in (
select distinct store
from sql server table)
You can create a table (or a volatile table if you do not have write privileges) to do this. Export result from SQL Server as text or into the language of your choice.
CREATE VOLATILE TABLE store_table (
column_1 datatype_1,
column_2 datatype_2,
...
column_n datatype_n);
You may need to add ON COMMIT PRESERVE ROWS before the ; to the above depending on your transaction settings.
From a language you can loop the below or do an execute many.
INSERT INTO store_table VALUES(value_1, value_2, ..., value_n);
Or you can use the import from text using Teradata SQL Assistant by going to File and selecting Import. Then execute the below and navigate to your file.
INSERT INTO store_table VALUES(?, ?, ..., n);
Once you have inserted your data you can query it by simply referencing the table name.
SELECT cmp_id,state,sde
FROM xyz
WHERE store IN(
SELECT store
FROM store_table)
The DISTINCT function is most easily done on export from SQL Server to minimize the rows you need to upload.
EDIT:
If you are doing this many times you can do this with a script, here is a very simple example in Python:
import pyodbc
con_ss = pyodbc.connect('sql_server_odbc_connection_string...')
crs_ss = con_ss.cursor()
con_td = pyodbc.connect('teradata_odbc_connection_string...')
crs_td = con_td.cursor()
# pull data for sql server
data_ss = crs_ss.execute('''
SELECT distinct store AS store
from store_Desc
''').fetchall()
# create table in teradata
crs_td.execute('''
CREATE VOLATILE TABLE store_table (
store DEC(4, 0)
) PRIMARY INDEX (store)
ON COMMIT PRESERVE ROWS;''')
con_td.commit()
# insert values; you can also use an execute many, but this is easier to read...
for row in data_ss:
crs_td.execute('''INSERT INTO store_table VALUES(?)''', row)
con_td.commit()
# get final data
data_td = crs_td.execute('''SELECT cmp_id,state,sde
FROM xyz
WHERE store IN(
SELECT store
FROM store_table);''').fetchall()
# from here write to file or whatever you would like.
Is fetching data from the Sql Server through ODBC an option?
The best option may be to use Teradata Parallel Transporter (TPT) to fetch data from SQL Server using its ODBC operator (as a producer) combined with Load or Update operator as the consumer to insert it into an intermediate table on Teradata. You must then perform rest of the operations on Teradata. For the rest of the operations, you can use BTEQ/SQLA to store the results in the final Teradata table. You can also put the same SQL in TPT's DDL operator instead of BTEQ/SQLA and get it done in a single job script.
To allow use of tables residing on separate DB environments (in your case SQL-Server and Teradata) in a single select statement, Teradata has recently released Teradata Query Grid. But I'm not sure about exact level of support for SQL-Server and it will involve licensing hassle and quite a learning curve to do this simple job.

How to execute remote query by Oracle Database Link

I use Oracle Database Link to query data from SQL Server. The query is like:
select *
from tableA#DL_SqlServer a
join tableB#DL_SqlServer b
on a.ID = b.ID
tableA and tableB is large and the result is relatively small. This query executes quickly in SQL Server since indexes are built both on the two tables. But it is very slow on Oracle Database Link to SQL Server. I guess the join operation is performed on Oracle side not on SQL Server side, thus the indexes are not used. Since I just need the joined result, I prefer to perform the query entirely on SQL Server and get the small result only. I konw that using SQL Server's linked server and OPENQUERY function can achieve this goal. I wonder how to do this on Oracle Database Link. Thanks! Btw, I have no privilege to create views on SQL Sevrer.
You most likely need to use the DBMS_HS_PASSTHROUGH package. Something like
DECLARE
l_cursor PLS_INTEGER;
BEGIN
l_cursor := dbms_hs_passthrough.open_cursor#dblink_to_sql_server;
dbms_hs_passthrough.parse#dblink_to_sql_server( l_cursor, <<select statement>> );
while dbms_hs_passthrough.fetch_row#link_to_sql_server(l_cursor) > 0
loop
dbms_hs_passthrough.get_value#dblink_to_sqlserver( l_cursor, 1, <<local variable for first column>> );
dbms_hs_passthrough.get_value#dblink_to_sqlserver( l_cursor, 2, <<local variable for second column>> );
...
end loop;
dbms_hs_passthrough.close_cursor#dblink_to_sqlserver( l_cursor );
END;

Resources