transform sql query to oracle - sql

i have to transform some query i´m using in SQL to Oracle code. I´m having a lot of trouble with tis. Does anyone know any Query transformer o something like that?. Can someone translate some part of this code for me?.
This is the code:
SELECT PRUEBA = CASE (SELECT TIMEATT FROM READER WHERE PANELID = DEVID AND READERID =
MACHINE) WHEN '1' THEN 'P10' ELSE 'P20' END
+ '0001'
+ CAST(YEAR(EVENT_TIME_UTC)AS VARCHAR)
+ Right('0' + Convert(VarChar(2), Month(EVENT_TIME_UTC)), 2)
+ Right('0' + Convert(VarChar(2), DAY(EVENT_TIME_UTC)), 2)
+ Right('0' + Convert(VarChar(2), DATEPART(HOUR,EVENT_TIME_UTC)), 2)
+ Right('0' + Convert(VarChar(2), DATEPART(MINUTE,EVENT_TIME_UTC)), 2)
+ Right('0' + Convert(VarChar(2), DATEPART(SECOND,EVENT_TIME_UTC)), 2)
+ CAST(YEAR(EVENT_TIME_UTC)AS VARCHAR)
+ Right('0' + Convert(VarChar(2), Month(EVENT_TIME_UTC)), 2)
+ Right('0' + Convert(VarChar(2), DAY(EVENT_TIME_UTC)), 2)
+ Right('0' + Convert(VarChar(2), DATEPART(HOUR,EVENT_TIME_UTC)), 2)
+ Right('0' + Convert(VarChar(2), DATEPART(MINUTE,EVENT_TIME_UTC)), 2)
+ Right('0' + Convert(VarChar(2), DATEPART(SECOND,EVENT_TIME_UTC)), 2)
+ Right('00000000' + Convert(VarChar(8), CARDNUM), 8)
+ Right('00000000' + Convert(VarChar(8), (SELECT SSNO FROM EMP WHERE ID = EMPID)), 8),
FROM events
WHERE eventid = 0 AND eventid = 0
and machine in (11) AND DEVID IN (1,2)
and CARDNUM <> 0 AND EMPID <> 0
and EVENT_TIME_UTC between '2006-02-16' AND '2007-02-09'
Many thanks for your help, i´ll keep looking.

Try this:
SELECT CASE (SELECT timeatt FROM reader WHERE panelid = devid AND readerid =
machine)
WHEN '1' THEN 'P10'
ELSE 'P20'
END
|| '0001'
|| To_char(event_time_utc, 'RRRRMMDDHH24MISS')
|| To_char(event_time_utc, 'RRRRMMDDHH24MISS')
|| Lpad(cardnum, 8, '0')
|| Lpad((SELECT ssno
FROM emp
WHERE id = empid), 8, '0') AS prueba
FROM events
WHERE eventid = 0
AND eventid = 0
AND machine IN ( 11 )
AND devid IN ( 1, 2 )
AND cardnum <> 0
AND empid <> 0
AND event_time_utc BETWEEN TO_DATE('2006-02-16', 'RRRR-MM-DD') AND TO_DATE('2007-02-09', 'RRRR-MM-DD')

I have recently had to make the same conversion from a life in tSQL to plSQL (oracle). A couple of "gotcha's" in the code you posted:
1) In tSQL the plus sign (for concatenation)+ is replaced in plSQL with double pipe ||
2) Most of the time you need a "Reference Cursor" (REF CURSOR) declared to put your results into like
PROCEDURE DEMO_SELECT_4_SO(
//other parameters followed by//
P_RESULT OUT REF CURSOR)
IS
BEGIN
OPEN P_RESULT FOR
SELECT
//fields///
FROM
a_table
WHERE
//you want..//
OR (as with a scalar result like your query) a single parameter of the correct type, like:
PROCEDURE DEMO_SELECT_4_SO(
//other parameters followed by//
P_RESULT OUT varchar2(60))
IS
BEGIN
SELECT
//concatenated fields///
INTO
P_RESULT
FROM
a_table
WHERE
//you want..//
NOTICE That select into in plSQL assigns the selected value to the target parameter and does not create a table as it would in tSQL
3) RIGHT (or LEFT) are SUBSTR functions in plSQL
I have found a lot of utility out of this link http://www.techonthenet.com/oracle/index.php for clear explanations of plSQL.

Related

SQL Server 2008 Alter Table Concatenate

I need to concatenate 2 ints and a varchar column into plan_no so it would look like this
Any help would be much appreciated.
We can try using CONVERT here to convert the numeric fields into text:
SELECT
CONVERT(varchar(10), lot) + '-' + forester + '-' +
CONVERT(varchar(10), year) AS plan_no
FROM yourTable;
If you want an update, then just use:
UPDATE yourTable
SET plan_no = CONVERT(varchar(10), lot) + '-' + forester + '-' +
CONVERT(varchar(10), year);
You need to do conversions :
select *, cast(lot as varchar(255)) + '-' +forester + '-' +cast([year] as varchar(5)) as plan_no
from table t;
You can alter your DDL :
alter table t
add plan_no as (cast(lot as varchar(255)) + '-' +forester + '-' +cast([year] as varchar(5)))
Edit :
update t
set plan_no = cast(lot as varchar(255)) + '-' +forester + '-' +cast([year] as varchar(5))
where plan_no is null;
I think you want to update data in your current table:
UPDATE TableName
SET plan_no = cast(lot as nvarchar(50)) + '-' + forester + '-' + cast([year] as nvarchar(50))
Please note: if lot, forester or year columns can contain nulls then you need to wrap values by ISNULL() function

Move aggregate logic to separate function in SQL Server 2008 R2

Please correct me if I'm using the wrong terminology or description, but I have business logic within an aggregate function (MIN and MAX). I wish to move to the logic to it's own function. I wish to do this so I don't have to make multiple changes in different locations when the client requests. I have the following
SELECT DISTINCT
DATA_MONTH,
DATA_DATE,
CASE
WHEN MIN(DATA_YEAR) = MAX(DATA_YEAR)
AND MIN(DATA_YEAR) = #BEGIN_YR THEN 'Started'
WHEN MIN(DATA_YEAR) = MAX(DATA_YEAR)
AND MIN(DATA_YEAR) <> #CURRENTFY THEN
CAST((MIN(DATA_YEAR) %100)-1 AS VARCHAR)
+ '/'
+ CAST(MIN(DATA_YEAR)%100 AS VARCHAR)
WHEN MIN(DATA_YEAR) <> MAX(DATA_YEAR)
AND MIN(DATA_YEAR) = #BEGIN_YR THEN
'Started' + ' from '
+ CAST((MAX(DATA_YEAR) %100)-1 AS VARCHAR)
+ '/'
+ CAST(MAX(DATA_YEAR)%100 AS VARCHAR)
ELSE CAST((MIN(DATA_YEAR) %100)-1 AS VARCHAR)
+ '/'
+ CAST((MIN(DATA_YEAR) %100) AS VARCHAR)
+ ' through '
+ CAST((MAX(DATA_YEAR) %100)-1 AS VARCHAR)
+ '/'
+ CAST(MAX(DATA_YEAR)%100 AS VARCHAR)
END AS [STATUS]
FROM TABLE_A
WHERE DATA_MONTH IN ('03', '04')
AND DATA_DATE = '01'
GROUP BY DATA_MONTH,
DATA_DATE
Which I would like to change it to this:
SELECT DISTINCT
DATA_MONTH,
DATA_DATE,
dbo.getStatus(DATA_YEAR) AS [STATUS]
FROM TABLE_A
WHERE DATA_MONTH IN ('03', '04')
AND DATA_DATE = '01'
GROUP BY DATA_MONTH,
DATA_DATE
The logic for getStatus() has the case statements and can output:
NULL
Started
15/16
Started from 15/16
15/16 through 16/17
My question is how can I restructure my logic to make this possible as I have a GROUP BY clause?
You can create a scalar user defined function and use it in the SELECT. Since it needs to be aggregated, you should be able to throw a MAX around it.
Although, I'd be interested to see if this works.
Nicarus is probably right and that you need a user defined aggregate function.
USE [AdventureWorks2012]
GO
/****** Object: Table [dbo].[TABLE_A] Script Date: 7/20/2016 3:23:39 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[TABLE_A](
[DATA_DATE] [date] NULL,
[DATA_MONTH] [int] NOT NULL,
[DATA_YEAR] [int] NOT NULL
) ON [PRIMARY]
GO
INSERT INTO TABLE_A SELECT CAST ('2016-03-02' as DATE) AS DATA_DATE, 3 as DATA_MONTH, 2016 AS DATA_YEAR
CREATE FUNCTION dbo.getStatus(#MAXYR int, #MINYR int, #BEGIN_YR int ,#CURRENTFY int)
RETURNS varchar(30)
AS
BEGIN
DECLARE #ret varchar(30);
SELECT #ret = CASE
WHEN #MINYR = #MAXYR
AND #MINYR = #BEGIN_YR THEN 'Started'
WHEN #MINYR = #MAXYR
AND #MINYR <> #CURRENTFY THEN
CAST((#MINYR %100)-1 AS VARCHAR)
+ '/'
+ CAST(#MINYR%100 AS VARCHAR)
WHEN #MINYR <> #MAXYR
AND #MINYR = #BEGIN_YR THEN
'Started' + ' from '
+ CAST((#MAXYR %100)-1 AS VARCHAR)
+ '/'
+ CAST(#MAXYR%100 AS VARCHAR)
ELSE CAST((#MINYR %100)-1 AS VARCHAR)
+ '/'
+ CAST((#MINYR %100) AS VARCHAR)
+ ' through '
+ CAST((#MAXYR %100)-1 AS VARCHAR)
+ '/'
+ CAST(#MAXYR%100 AS VARCHAR)
END
RETURN #ret;
END;
DECLARE #BEGIN_YR INT = 2;
DECLARE #CURRENTFY int = 2016;
SELECT DISTINCT
DATA_MONTH,
DATA_DATE,
dbo.getStatus(MAX(DATA_YEAR), MIN(DATA_YEAR), #BEGIN_YR, #CURRENTFY) as STATUS
FROM TABLE_A
GROUP BY DATA_MONTH, DATA_DATE

SQL Group By Query

I have the following table with one column ArbPlWPos:
+------------+
+ IH-MKE +
+ IH-MKEEA +
+ IH-MKEEB +
+ IH-MKEPE +
+ IH-MKEPM +
+ IH-MVKE1 +
+ IH-MVKM1 +
+------------+
I can run a statement in MS Access which groups by the first 6 letters:
SELECT left(ArbPlWPos, 6), count(left(ArbPlWPos, 6))
FROM my_table
GROUP BY left(ArbPlWPos, 6)
+------------+------+
+ IH-MKE + 10 +
+ IH-MKM + 20 +
+ IH-MVK + 30 +
+------------+------+
How to include the IH-MVK into the IH-MKE, so the result should be:
+------------+------+
+ IH-MKE + 40 +
+ IH-MKM + 20 +
+------------+------+
Is this somehow possible with SQL/Access?
In MS Access, you can do this using a conditional expression, iif():
SELECT iif(ArbPlWPos like "IH-MVK*", "IH-MKE", left(ArbPlWPos, 6)),
count(*)
FROM TABLE
GROUP BY iif(ArbPlWPos like "IH-MVK*", "IH-MKE", left(ArbPlWPos, 6));
You can group by any expression, but you are to repeat it after SELECT (is you need) and after GROUP BY as you did with an usual column. For example:
SELECT my_function_or_expression(column_A, column_B), count(1)
FROM my_table
GROUP BY my_function_or_expression(column_A, column_B);
In your case it will be:
SELECT
CASE WHEN left(ArbPlWPos, 6) = 'IH-MVK'
THEN 'IH-MKE'
ELSE left(ArbPlWPos, 6) END AS cutArbPlWPos,
count(1) AS amount
FROM my_table
GROUP BY CASE WHEN left(ArbPlWPos, 6) = 'IH-MVK'
THEN 'IH-MKE'
ELSE left(ArbPlWPos, 6) END;
You can also simplify it using subquery.
SELECT cutArbPlWPos, count(1)
FROM (SELECT
CASE WHEN left(ArbPlWPos, 6) = 'IH-MVK'
THEN 'IH-MKE'
ELSE left(ArbPlWPos, 6) END AS cutArbPlWPos
FROM my_table
)
GROUP BY cutArbPlWPos;

ISNULL is still returning NULL values

I've this query:
SELECT cod_commessa, (ISNULL(ccomm.costi, 0) + ISNULL(ccomm.imp_costi, 0) - ISNULL(ccomm.rid_costi, 0)) -
((SELECT ISNULL(costi, 0) AS Expr1
FROM t_costi_commesse AS tbs
WHERE (cod_commessa = ccomm.cod_commessa) AND (anno = YEAR(DATEADD(m, - 1, CAST(CAST(ccomm.anno AS varchar) + REPLICATE('0',
2 - LEN(CAST(ccomm.mese AS varchar))) + CAST(ccomm.mese AS varchar) + '01' AS smalldatetime)))) AND (mese = MONTH(DATEADD(m, - 1,
CAST(CAST(ccomm.anno AS varchar) + REPLICATE('0', 2 - LEN(CAST(ccomm.mese AS varchar))) + CAST(ccomm.mese AS varchar)
+ '01' AS smalldatetime))))) +
(SELECT ISNULL(imp_costi, 0) AS Expr1
FROM t_costi_commesse AS tbs
WHERE (cod_commessa = ccomm.cod_commessa) AND (anno = YEAR(DATEADD(m, - 1, CAST(CAST(ccomm.anno AS varchar) + REPLICATE('0',
2 - LEN(CAST(ccomm.mese AS varchar))) + CAST(ccomm.mese AS varchar) + '01' AS smalldatetime)))) AND (mese = MONTH(DATEADD(m, - 1,
CAST(CAST(ccomm.anno AS varchar) + REPLICATE('0', 2 - LEN(CAST(ccomm.mese AS varchar))) + CAST(ccomm.mese AS varchar)
+ '01' AS smalldatetime))))) -
(SELECT ISNULL(rid_costi, 0) AS Expr1
FROM t_costi_commesse AS tbs
WHERE (cod_commessa = ccomm.cod_commessa) AND (anno = YEAR(DATEADD(m, - 1, CAST(CAST(ccomm.anno AS varchar) + REPLICATE('0',
2 - LEN(CAST(ccomm.mese AS varchar))) + CAST(ccomm.mese AS varchar) + '01' AS smalldatetime)))) AND (mese = MONTH(DATEADD(m, - 1,
CAST(CAST(ccomm.anno AS varchar) + REPLICATE('0', 2 - LEN(CAST(ccomm.mese AS varchar))) + CAST(ccomm.mese AS varchar)
+ '01' AS smalldatetime)))))) AS 'costi'
FROM t_costi_commesse AS ccomm INNER JOIN
t_commesse AS comm ON ccomm.cod_commessa = comm.codcema
This query is returning values correctly, but sometimes I have some values in column 'costi' that still are NULL, even if I apply ISNULL to every value. The weird thing is that sometimes a NULL value is correctly replaced with 0, but sometimes not.
I'm also sure that the original value is NULL (and not maybe a string 'NULL'), because SQL Server Management Studio changes correctly the background color.
So, I can understand if my query is incorrect or if ISNULL in not working properly for an unknown reason. Any suggestion?
Move your ISNULLs that you're applying within your subqueries to the outside.
This:
select 1,(select object_id from sys.objects where 1=0)
Produces:
1, NULL
Despite the fact that object_id isn't nullable, because the subquery returns no rows. You can't fix it in the select of the subquery because there are no rows. So this:
select 1,(select ISNULL(object_id,0) from sys.objects where 1=0)
doesn't fix the issue but this:
select 1,ISNULL((select object_id from sys.objects where 1=0),0)
does.

how to parse for more than 4 positions

I have a funny case where a piece of data needed, is actually embedded in a column of data looking something like this:
note that is a shop with strong legacy mess still in place.
adlu201008270919_3.zip the date is what i need and is embedded.
I have code to do this here:
AND CAST(SUBSTRING(M.MDS_FILE,5,4) + '-' + SUBSTRING(M.MDS_FILE,9,2) + '-' + SUBSTRING(M.MDS_FILE,11,2) as datetime)
But now I find out that where you have here 'adlu' that is 4 pos. It can be 3 or 2 or 1.
So I have to code for that I have come up with this: but it's not compiling:
AND CASE WHEN WHEN CAST(SUBSTRING(M.MDS_FILE,5,4) + '-' + SUBSTRING(M.MDS_FILE,9,2) + '-' + SUBSTRING(M.MDS_FILE,11,2) as datetime)
ELSE WHEN OEN.LENGTH(S.FACILITY_KEY) = 3 THEN CAST(SUBSTRING(M.MDS_FILE,4,4) + '-' + SUBSTRING(M.MDS_FILE,8,2) + '-' + SUBSTRING(M.MDS_FILE,10,2) as datetime)
ELSE WHEN OEN.LENGTH(S.FACILITY_KEY) = 2 THEN CAST(SUBSTRING(M.MDS_FILE,3,4) + '-' + SUBSTRING(M.MDS_FILE,7,2) + '-' + SUBSTRING(M.MDS_FILE,9,2) as datetime)
ELSE CAST(SUBSTRING(M.MDS_FILE,2,4) + '-' + SUBSTRING(M.MDS_FILE,6,2) + '-' + SUBSTRING(M.MDS_FILE,8,2) as datetime) END
CASE requires an evaluation. Your first statement just says WHEN(a bunch of conversions) but there's never an evaluation (=, <, > etc).
I'm assuming you want that to be AND CASE WHEN OEN.LENGTH(s.FACILITY_KEY) = 4 THEN ...
Instead of a CASE statement based of S.FACILITY_KEY, I would use PATINDEX to dynamically find the start position of the date string that you're looking for:
DECLARE
#TestValue1 VARCHAR(50),
#TestValue2 VARCHAR(50),
#TestValue3 VARCHAR(50),
#TestValue4 VARCHAR(50)
SET #TestValue1 = 'adlu201008270919_3.zip'
SET #TestValue2 = 'adl201008270919_3.zip'
SET #TestValue3 = 'ad201008270919_3.zip'
SET #TestValue4 = 'a201008270919_3.zip'
SELECT CAST(SUBSTRING(#TestValue1, PATINDEX('%[1-2][0-9][0-9][0-9][0-9][0-9][0-9][0-9]%', #TestValue1), 8) AS DATETIME)
SELECT CAST(SUBSTRING(#TestValue2, PATINDEX('%[1-2][0-9][0-9][0-9][0-9][0-9][0-9][0-9]%', #TestValue2), 8) AS DATETIME)
SELECT CAST(SUBSTRING(#TestValue3, PATINDEX('%[1-2][0-9][0-9][0-9][0-9][0-9][0-9][0-9]%', #TestValue3), 8) AS DATETIME)
SELECT CAST(SUBSTRING(#TestValue4, PATINDEX('%[1-2][0-9][0-9][0-9][0-9][0-9][0-9][0-9]%', #TestValue4), 8) AS DATETIME)