how to parse for more than 4 positions - sql

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)

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

CAST number as varchar, then update into another table as date

I'll as brief as possible, but start by saying I'm a network guy, not a DBA.
SQL Server Enterprise 11.0.5343
Scenario - Need to get three columns (each with a part of a date) together, and then update another table with the full date.
Source table: UT210AP
Columns:
UTONMM (Utility On Month - 2 digit)
UTONDD (Utility On Day - 2 digit)
UTONYY (Utility On Year - 2 digit)
UTONCV (Utility On Century - 0 = 19xx, 1 = 20xx)
I can select the data into a "date" with this code (the source data is on an IBM AS/400 linked server)
CAST(UTONMM as varchar) + '/' +
CAST(UTONDD as varchar) + '/' +
CASE WHEN UTONCV = '1'
THEN
RIGHT('20' + CONVERT(varchar(4), RIGHT('00' + CONVERT(varchar(4),UTONYY),2)),4)
ELSE
RIGHT('19' + CONVERT(varchar(4), UTONYY),4)
END AS UTON
And I get these results in the column I named "UTON":
4/6/1994
7/1/1988
11/14/1990
6/6/2014
QUESTION:
I have a nightly import job that runs, and I need to get the "date" (like 4/6/1994) into a field called TIME_CONNECT as part of this update statement from the job:
Update [responder].[Temp_RX_CUSTOMERS]
set CustomerID = lf.UTCSID
from [responder].[Temp_RX_CUSTOMERS] LEFT Outer Join
[HTEDTA].[THOR].[HTEDTA].UT210AP lf ON [responder].[Temp_RX_CUSTOMERS].LocationID = lf.UTLCID
where lf.UTOFMM = 0
The "UTOFMM" in the code above is "Utility Off Month", I don't even care about checking for it's value, I just want to get the "UTON" date from the top select statement into the "TIME_CONNECT" field in the "Temp_RX_CUSTOMERS" field.
Is this what you want? This copies the value into the field, assuming time_connect is a string.
Update [responder].[Temp_RX_CUSTOMERS]
set CustomerID = lf.UTCSID,
time_connect = (CAST(UTONMM as varchar) + '/' +
CAST(UTONDD as varchar) + '/' +
(CASE WHEN UTONCV = '1'
THEN RIGHT('20' + CONVERT(varchar(4), RIGHT('00' + CONVERT(varchar(4),UTONYY),2)),4)
ELSE RIGHT('19' + CONVERT(varchar(4), UTONYY),4)
END)
)
from [responder].[Temp_RX_CUSTOMERS] LEFT Outer Join
[HTEDTA].[THOR].[HTEDTA].UT210AP lf
ON [responder].[Temp_RX_CUSTOMERS].LocationID = lf.UTLCID
where lf.UTOFMM = 0;
If time_connect is a date/datetime data type, you can use datefromparts() (available in SQL Server 2012+):
Update [responder].[Temp_RX_CUSTOMERS]
set CustomerID = lf.UTCSID,
time_connect = DATEFROMPARTS(1800 + UTONCV * 100 + UNONYY,
UTONMM, UTONDD)
from [responder].[Temp_RX_CUSTOMERS] LEFT Outer Join
[HTEDTA].[THOR].[HTEDTA].UT210AP lf
ON [responder].[Temp_RX_CUSTOMERS].LocationID = lf.UTLCID
where lf.UTOFMM = 0;

Update column with concatenated date (SQL Server)

I'm trying to update a column with the concatenated and converted results of two other columns in order to create a column with a date field. The SELECT statement returns the values I want to Update with, but I'm missing something (probably simple) on the update. It won't execute because
"the subquery returns more than one value".
However, I don't want to update with the same value for each row, but rather the concatenated result for each row.
What am I missing?
UPDATE myTable
SET myDate =
(
SELECT
CONVERT (Date,(CONVERT (NVarchar, CreatedYear) + '-' + CONVERT (NVarchar, CreatedMonth) + '-' + '01') ,0)
FROM myTable
)
I believe you have an extra SELECT that is not required. Please try:
UPDATE myTable
SET myDate =
CONVERT (Date,(CONVERT (NVarchar, CreatedYear) + '-' + CONVERT (NVarchar, CreatedMonth) + '-' + '01') ,0)
FROM myTable
This is a bit more readable in my opinion:
UPDATE dbo.tblControlMaster SET AuditAddDate = CAST(CreatedYear AS NVARCHAR(4)) + '-' + CAST(CreatedMonth AS NVARCHAR(2)) + '-' + '01'

transform sql query to oracle

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.

How to format a numeric column as phone number in SQL

I have table in the database with a phone number column. The numbers look like this:
123456789
I want to format that to look like this:
123-456-789
This should do it:
UPDATE TheTable
SET PhoneNumber = SUBSTRING(PhoneNumber, 1, 3) + '-' +
SUBSTRING(PhoneNumber, 4, 3) + '-' +
SUBSTRING(PhoneNumber, 7, 4)
Incorporated Kane's suggestion, you can compute the phone number's formatting at runtime. One possible approach would be to use scalar functions for this purpose (works in SQL Server):
CREATE FUNCTION FormatPhoneNumber(#phoneNumber VARCHAR(10))
RETURNS VARCHAR(12)
BEGIN
RETURN SUBSTRING(#phoneNumber, 1, 3) + '-' +
SUBSTRING(#phoneNumber, 4, 3) + '-' +
SUBSTRING(#phoneNumber, 7, 4)
END
I'd generally recommend you leave the formatting up to your front-end code and just return the data as-is from SQL. However, to do it in SQL, I'd recommend you create a user-defined function to format it. Something like this:
CREATE FUNCTION [dbo].[fnFormatPhoneNumber](#PhoneNo VARCHAR(20))
RETURNS VARCHAR(25)
AS
BEGIN
DECLARE #Formatted VARCHAR(25)
IF (LEN(#PhoneNo) <> 10)
SET #Formatted = #PhoneNo
ELSE
SET #Formatted = LEFT(#PhoneNo, 3) + '-' + SUBSTRING(#PhoneNo, 4, 3) + '-' + SUBSTRING(#PhoneNo, 7, 4)
RETURN #Formatted
END
GO
Which you can then use like this:
SELECT [dbo].[fnFormatPhoneNumber](PhoneNumber) AS PhoneNumber
FROM SomeTable
It has a safeguard in, in case the phone number stored isn't the expected number of digits long, is blank, null etc - it won't error.
EDIT: Just clocked on you want to update your existing data. The main bit that's relevant from my answer then is that you need to protect against "dodgy"/incomplete data (i.e. what if some existing values are only 5 characters long)
Above users mentioned, those solutions are very basic and they won't work if the database has different phone formats like:
(123)123-4564
123-456-4564
1234567989
etc
Here is a more complex solution that will work with ANY input given:
CREATE FUNCTION [dbo].[ufn_FormatPhone] (#PhoneNumber VARCHAR(32))
RETURNS VARCHAR(32)
AS
BEGIN
DECLARE #Phone CHAR(32)
SET #Phone = #PhoneNumber
-- cleanse phone number string
WHILE PATINDEX('%[^0-9]%', #PhoneNumber) > 0
SET #PhoneNumber = REPLACE(#PhoneNumber, SUBSTRING(#PhoneNumber, PATINDEX('%[^0-9]%', #PhoneNumber), 1), '')
-- skip foreign phones
IF (
SUBSTRING(#PhoneNumber, 1, 1) = '1'
OR SUBSTRING(#PhoneNumber, 1, 1) = '+'
OR SUBSTRING(#PhoneNumber, 1, 1) = '0'
)
AND LEN(#PhoneNumber) > 11
RETURN #Phone
-- build US standard phone number
SET #Phone = #PhoneNumber
SET #PhoneNumber = '(' + SUBSTRING(#PhoneNumber, 1, 3) + ') ' + SUBSTRING(#PhoneNumber, 4, 3) + '-' + SUBSTRING(#PhoneNumber, 7, 4)
IF LEN(#Phone) - 10 > 1
SET #PhoneNumber = #PhoneNumber + ' X' + SUBSTRING(#Phone, 11, LEN(#Phone) - 10)
RETURN #PhoneNumber
END
I do not recommend keeping bad data in the database and then only correcting it on the output. We have a database where phone numbers are entered in variously as :
(555) 555-5555
555+555+5555
555.555.5555
(555)555-5555
5555555555
Different people in an organization may write various retrieval functions and updates to the database, and therefore it would be harder to set in place formatting and retrieval rules. I am therefore correcting the data in the database first and foremost and then setting in place rules and form validations that protect the integrity of this database going forward.
I see no justification for keeping bad data unless as suggested a duplicate column be added with corrected formatting and the original data kept around for redundancy and reference, and YES I consider badly formatted data as BAD data.
Solutions that use SUBSTRING and concatenation + are nearly independent of RDBMS. Here is a short solution that is specific to SQL Server:
declare #x int = 123456789
select stuff(stuff(#x, 4, 0, '-'), 8, 0, '-')
You can also try this:
CREATE function [dbo].[fn_FormatPhone](#Phone varchar(30))
returns varchar(30)
As
Begin
declare #FormattedPhone varchar(30)
set #Phone = replace(#Phone, '.', '-') --alot of entries use periods instead of dashes
set #FormattedPhone =
Case
When isNumeric(#Phone) = 1 Then
case
when len(#Phone) = 10 then '('+substring(#Phone, 1, 3)+')'+ ' ' +substring(#Phone, 4, 3)+ '-' +substring(#Phone, 7, 4)
when len(#Phone) = 7 then substring(#Phone, 1, 3)+ '-' +substring(#Phone, 4, 4)
else #Phone
end
When #phone like '[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9][0-9][0-9][0-9]' Then '('+substring(#Phone, 1, 3)+')'+ ' ' +substring(#Phone, 5, 3)+ '-' +substring(#Phone, 8, 4)
When #phone like '[0-9][0-9][0-9] [0-9][0-9][0-9] [0-9][0-9][0-9][0-9]' Then '('+substring(#Phone, 1, 3)+')'+ ' ' +substring(#Phone, 5, 3)+ '-' +substring(#Phone, 9, 4)
When #phone like '[0-9][0-9][0-9]-[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]' Then '('+substring(#Phone, 1, 3)+')'+ ' ' +substring(#Phone, 5, 3)+ '-' +substring(#Phone, 9, 4)
Else #Phone
End
return #FormattedPhone
end
use on it select
(SELECT [dbo].[fn_FormatPhone](f.coffphone)) as 'Phone'
Output will be
You Can Use FORMAT if you column is a number Syntax like
FORMAT ( value, format [, culture ] ) In use like
FORMAT ( #d, 'D', 'en-US' ) or FORMAT(123456789,'###-##-####') (But This works for only SQL SERVER 2012 And After)
In Use Like
UPDATE TABLE_NAME SET COLUMN_NAME = FORMAT(COLUMN_NAME ,'###-##-####')
And
if your column is Varchar Or Nvarchar use do like this
CONCAT(SUBSTRING(CELLPHONE,0,4),' ',SUBSTRING(CELLPHONE,4,3),' ',SUBSTRING(CELLPHONE,7,2) ,' ',SUBSTRING(CELLPHONE,9,2) )
You can always get help from
https://msdn.microsoft.com/en-us/library/hh213505.aspx
I found that this works if wanting in a (123) - 456-7890 format.
UPDATE table
SET Phone_number = '(' +
SUBSTRING(Phone_number, 1, 3)
+ ') '
+ '- ' +
SUBSTRING(Phone_number, 4, 3)
+ '-' +
SUBSTRING(Phone_number, 7, 4)
Updated #sqiller's function for my purposes
CREATE FUNCTION [toolbox].[FormatPhoneNumber] (
#PhoneNumber VARCHAR(50),
#DefaultIfUnknown VARCHAR(50)
)
RETURNS VARCHAR(50)
AS
BEGIN
-- remove any extension
IF CHARINDEX('x', #PhoneNumber, 1) > 0
SET #PhoneNumber = SUBSTRING(#PhoneNumber, 1, CHARINDEX('x', #PhoneNumber, 1) - 1)
-- cleanse phone number string
WHILE PATINDEX('%[^0-9]%',#PhoneNumber) > 0
SET #PhoneNumber = REPLACE(#PhoneNumber,
SUBSTRING(#PhoneNumber,PATINDEX('%[^0-9]%',#PhoneNumber),1),'')
-- Remove US international code if exists, i.e. 12345678900
IF SUBSTRING(#PhoneNumber,1,1) = '1' AND LEN(#PhoneNumber) = 11
SET #PhoneNumber = SUBSTRING(#PhoneNumber, 2, 10)
-- any phone numbers without 10 characters are set to default
IF LEN(#PhoneNumber) <> 10
RETURN #DefaultIfUnknown
-- build US standard phone number
SET #PhoneNumber = '(' + SUBSTRING(#PhoneNumber,1,3) + ') ' +
SUBSTRING(#PhoneNumber,4,3) + '-' + SUBSTRING(#PhoneNumber,7,4)
RETURN #PhoneNumber
END
If you want to just format the output no need to create a new table or a function. In this scenario the area code was on a separate fields. I use field1, field2 just to illustrate you can select other fields in the same query:
area phone
213 8962102
Select statement:
Select field1, field2,areacode,phone,SUBSTR(tablename.areacode,1,3) + '-' + SUBSTR(tablename.phone,1,3) + '-' + SUBSTR(tablename.areacode,4,4) as Formatted Phone from tablename
Sample OUTPUT:
columns: FIELD1, FIELD2, AREA, PHONE, FORMATTED PHONE
data: Field1, Field2, 213, 8962102, 213-896-2102