Update Column: Case With Concat - sql

I am have a blank column, it is called column_blank. I want to concat two other columns (concat1, concat2) and based on the concat value, add a value into column_blank. I am extremely green and appreciate your help.
This is what I am thinking. I am not too confident about the DECLARE statement
DECLARE DIRECTION CONCAT := (CONCAT1, CONCAT2);
INSERT INTO
MYDATA_EXTRACT_DATA.COLUMN_BLANK
SELECT
CASE COLUMN_BLANK
WHEN (DIRECTION) IS '123456', THEN ('654321'),
WHEN (DIRECTION) IS '789101', THEN ('654321'),
ELSE '000'
END CASE
FROM MYDATA_EXTRACT_DATA

That's just an ordinary update statement:
update mydata_extract_data set
column_blank = case when concat1 || concat2 in ('123456', '789101') then '654321'
else '000'
end;

Related

Oracle ORA-12704 with case expression on CLOB

I have an Oracle update statement with a case that is trying to either set or ignore a value (leave original value the same ).
With this code, either of the two individual sets compile on their own ( the two commented out ones ).
But when combined in a case statement, I get "PL/SQL: ORA-12704: character set mismatch"
The column is a CLOB column.
Alternatively is there a way to conditionally not do a set in an update statement?
LONGDESCRIPT = ( CASE v_CanUpdateAssetDescription WHEN 1 THEN p_description ELSE LONGDESCRIPT END ),
-- LONGDESCRIPT = LONGDESCRIPT,
--LONGDESCRIPT = p_description,
Apparently the character set of p_description is not the same as that of LONGDESCRIPT. In a simple assignment Oracle can work with this, but in a CASE expression all values returned from the different paths through the CASE expression must be of exactly the same type. As it appears you're doing this in PL/SQL you might try doing something like the following:
DECLARE
cCLOB_var YOUR_TABLE.LONGDESCRIPT%TYPE;
BEGIN
cCLOB_var := p_description;
UPDATE YOUR_TABLE
SET LONGDESCRIPT = CASE v_CanUpdateAssetDescription
WHEN 1 THEN cCLOB_var
ELSE LONGDESCRIPT
END
...etc...
END;
You might also try using a CAST:
UPDATE YOUR_TABLE
SET LONGDESCRIPT = CASE v_CanUpdateAssetDescription
WHEN 1 THEN CAST(p_description AS YOUR_TABLE.LONGDESCRIPT%TYPE)
ELSE LONGDESCRIPT
END
Not sure if the latter will work or not, but it might be worth a shot.
Oddly I found that to_clob did the trick.
And even more oddly, I only needed TO_CLOB for the LONGDESCRIPT value.
LONGDESCRIPT = ( CASE v_CanUpdateAssetDescription WHEN 1 THEN p_description ELSE to_clob(LONGDESCRIPT) END ),

SQL: How to make a replace on the field ''

I have a very but tricky question for you guys. So, listen I have a field with spaces and numbers in one of my table columns. The key part is transform the content in a decimal field. The drawback is basically that for some rows I could get something like:
' 1584.00 '
' 156546'
'545.00 '
' '
So, to clean up my column, I have done a LTRIM and RTRIM so spaces gone. So now for a couple of records where the record were just spaces the new content is ''. Finally I need to convert this result to a decimal.
Issue: The thing is that for field that contend just the spaces the new result is '' and I'm not able to apply a REPLACE on this because it's a blank and the code below doesn't work:
SELECT REPLACE('','','0')
-- Final current verison
SELECT CAST(COALESCE(REPLACE(REPLACE([Gross_Weight],' ','0'),',',''),'0') AS DECIMAL(13,3))
How could I figure it out?
thanks so much
SELECT COALESCE(NULLIF(MyColumn, ''), 0)
This has the side-effect that you will also turn NULL values into 0, which you might not want. If that's a problem then a simple CASE statement should do the trick:
SELECT CASE WHEN MyColumn = '' THEN 0 ELSE CAST(MyColumn AS DECIMAL(10, 4)) END
Obviously you'll also have to incorporate any other manipulations that you're already doing.
No need for replace, just concatenate a zero to your column, like
SELECT RTRIM('0' + LTRIM(column))
I presume your data is in a table.
Lets call this table 'DATA' and the column 'VALUE'
Then you might use the below query
UPDATE DATA SET VALUE = 0 where VALUE = ''
To select the value do the below
select case ltrim(rtrim([Gross_Weight])) when ''
THEN 0
ELSE ltrim(rtrim([Gross_Weight])) END
Let me know if i get the requirement wrong.

Procedure to apply formatting to all rows in a table

I had a SQL procedure that increments through each row and and pads some trailing zeros on values depending on the length of the value after a decimal point. Trying to carry this over to a PSQL environment I realized there was a lot of syntax differences between SQL and PSQL. I managed to make the conversion over time but I am still getting a syntax error and cant figure out why. Can someone help me figure out why this wont run? I am currently running it in PGadmin if that makes any difference.
DO $$
DECLARE
counter integer;
before decimal;
after decimal;
BEGIN
counter := 1;
WHILE counter <> 2 LOOP
before = (select code from table where ID = counter);
after = (SELECT SUBSTRING(code, CHARINDEX('.', code) + 1, LEN(code)) as Afterward from table where ID = counter);
IF before = after
THEN
update table set code = before + '.0000' where ID = counter;
ELSE
IF length(after) = 1 THEN
update table set code = before + '000' where ID = counter;
ELSE IF length(after) = 2 THEN
update table set code = before + '00' where ID = counter;
ELSE IF length(after) = 3 THEN
update table set code = before + '0' where ID = counter;
ELSE
select before;
END IF;
END IF;
counter := counter + 1;
END LOOP
END $$;
Some examples of the input/output of the intended result:
Input 55.5 > Output 55.5000
Input 55 > Output 55.0000
Thanks for your help,
Justin
There is no need for a function or even an update on the table to format values when displaying them.
Assuming the values are in fact numbers stored in a decimal or float column, all you need to do is to apply the to_char() function when retrieving them:
select to_char(code, 'FM999999990.0000')
from data;
This will output 55.5000 or 55.0000
The drawback of the to_char() function is that you need to anticipate the maximum number of digits of that can occur. If you have not enough 9 in the format mask, the output will be something like #.###. But as too many digits in the format mask don't hurt, I usually throw a lot into the format mask.
For more information on formatting functions, please see the manual: https://www.postgresql.org/docs/current/static/functions-formatting.html#FUNCTIONS-FORMATTING-NUMERIC-TABLE
If you insist on storing formatted data, you can use to_char() to update the table:
update the_table
set code = to_char(code::numeric, 'FM999999990.0000');
Casting the value to a number will of course fail if there a non-numeric values in the column.
But again: I strong recommend to store numbers as numbers, not as strings.
If you want to compare this to a user input, it's better to convert the user input to a proper number and compare that to the (number) values stored in the database.
The string matching that you are after doesn't actually require a function either. Using substring() with a regex will do that:
update the_table
set code = code || case length(coalesce(substring(code from '\.[0-9]*$'), ''))
when 4 then '0'
when 3 then '00'
when 2 then '000'
when 1 then '0000'
when 0 then '.0000'
else ''
end
where length(coalesce(substring(code from '\.[0-9]*$'), '')) < 5;
substring(code from '\.[0-9]*$') extracts everything the . followed by numbers that is at the end of the string. So for 55.0 it returns .0 for 55.50 it returns .50 if there is no . in the value, then it returns null that's why the coalesce is needed.
The length of that substring tells us how many digits are present. Depending on that we can then append the necessary number of zeros. The case can be shortened so that not all possible length have to be listed (but it's not simpler):
update the_table
set code = code || case length(coalesce(substring(code from '\.[0-9]*$'), ''))
when 0 then '.0000'
else lpad('0', 5- length(coalesce(substring(code from '\.[0-9]*$'), '')), '0')
end
where length(coalesce(substring(code from '\.[0-9]*$'), '')) < 5;
Another option is to use the position of the . inside the string to calculate the number of 0 that need to be added:
update the_table
set code =
code || case
when strpos(code, '.') = 0 then '0000'
else rpad('0', 4 - (length(code) - strpos(code, '.')), '0')
end
where length(code) - strpos(code, '.') < 4;
Regular expressions are quite expensive not using them will make this faster. The above will however only work if there is always at most one . in the value.
But if you can be sure that every value can be cast to a number, the to_char() method with a cast is definitely the most robust one.
To only process rows where the code columns contains correct numbers, you can use a where clause in the SQL statement:
where code ~ '^[0-9]+(\.[0-9][0-9]?)?$'
To change the column type to numeric:
alter table t alter column code type numeric

How to remove the first character if it is a specific character in SQL

I currently have a table Telephone it has entries like the following:
9073456789101
+773456789101
0773456789101
What I want to do is remove only the 9 from the start of all the entries that have a 9 there but leave the others as they are.
any help would be greatly appreciated.
While all other answer are probably also working, I'd suggest to try and use STUFF function to easily replace a part of the string.
UPDATE Telephone
SET number = STUFF(number,1,1,'')
WHERE number LIKE '9%'
SQLFiddle DEMO
Here is the code and a SQLFiddle
SELECT CASE
WHEN substring(telephone_number, 1, 1) <> '9'
THEN telephone_number
ELSE substring(telephone_number, 2, LEN(telephone_number))
END
FROM Telephone
Update Telephone set number = RIGHT(number,LEN(number)-1) WHERE number LIKE '9%';
I recently solved a similar problem with a combination of RIGHT(), LEN() & PATINDEX(). PATINDEX will return the integer 1 when it finds a 9 as the first character and 0 otherwise. This method allows all records to be returned at once without a CASE WHEN statement.
SELECT
RIGHT(number, LEN(number) - PATINDEX('9%', number))
FROM Telephone
UPDATE dbo.Telephone
SET column_name = SUBSTRING(column_name, 2, 255)
WHERE column_name LIKE '9%';
Stuff is a great function for this. However, using it with an update statement with a where clause is great, but what if I was doing an insert, and I needed all of the rows inserted in one pass. The below will remove the first character if it is a period, does not use the slower case statement, and converts nulls to an empty string.
DECLARE #Attachment varchar(6) = '.GIF',
#Attachment2 varchar(6)
SELECT
#Attachment2 = ISNULL(ISNULL(NULLIF(LEFT(#Attachment, 1), '.'), '') + STUFF(#Attachment, 1, 1, ''), '')
SELECT
#Attachment2
DECLARE #STR nvarchar(200) = 'TEST'
SET #STR = STUFF(#STR,1,1,'')
PRINT #STR
Result will be "EST"
You can use replace in select statement instead of where or update
SELECT REPLACE(REPLACE('_'+number,'_9',''),'_','') FROM #tbl

Removing leading zeroes from a field in a SQL statement

I am working on a SQL query that reads from a SQLServer database to produce an extract file. One of the requirements to remove the leading zeroes from a particular field, which is a simple VARCHAR(10) field. So, for example, if the field contains '00001A', the SELECT statement needs to return the data as '1A'.
Is there a way in SQL to easily remove the leading zeroes in this way? I know there is an RTRIM function, but this seems only to remove spaces.
select substring(ColumnName, patindex('%[^0]%',ColumnName), 10)
select replace(ltrim(replace(ColumnName,'0',' ')),' ','0')
You can use this:
SELECT REPLACE(LTRIM(REPLACE('000010A', '0', ' ')),' ', '0')
I had the same need and used this:
select
case
when left(column,1) = '0'
then right(column, (len(column)-1))
else column
end
select substring(substring('B10000N0Z', patindex('%[0]%','B10000N0Z'), 20),
patindex('%[^0]%',substring('B10000N0Z', patindex('%[0]%','B10000N0Z'),
20)), 20)
returns N0Z, that is, will get rid of leading zeroes and anything that comes before them.
If you want the query to return a 0 instead of a string of zeroes or any other value for that matter you can turn this into a case statement like this:
select CASE
WHEN ColumnName = substring(ColumnName, patindex('%[^0]%',ColumnName), 10)
THEN '0'
ELSE substring(ColumnName, patindex('%[^0]%',ColumnName), 10)
END
In case you want to remove the leading zeros from a string with a unknown size.
You may consider using the STUFF command.
Here is an example of how it would work.
SELECT ISNULL(STUFF(ColumnName
,1
,patindex('%[^0]%',ColumnName)-1
,'')
,REPLACE(ColumnName,'0','')
)
See in fiddler various scenarios it will cover
https://dbfiddle.uk/?rdbms=sqlserver_2012&fiddle=14c2dca84aa28f2a7a1fac59c9412d48
You can try this - it takes special care to only remove leading zeroes if needed:
DECLARE #LeadingZeros VARCHAR(10) ='-000987000'
SET #LeadingZeros =
CASE WHEN PATINDEX('%-0', #LeadingZeros) = 1 THEN
#LeadingZeros
ELSE
CAST(CAST(#LeadingZeros AS INT) AS VARCHAR(10))
END
SELECT #LeadingZeros
Or you can simply call
CAST(CAST(#LeadingZeros AS INT) AS VARCHAR(10))
Here is the SQL scalar value function that removes leading zeros from string:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: Vikas Patel
-- Create date: 01/31/2019
-- Description: Remove leading zeros from string
-- =============================================
CREATE FUNCTION dbo.funRemoveLeadingZeros
(
-- Add the parameters for the function here
#Input varchar(max)
)
RETURNS varchar(max)
AS
BEGIN
-- Declare the return variable here
DECLARE #Result varchar(max)
-- Add the T-SQL statements to compute the return value here
SET #Result = #Input
WHILE LEFT(#Result, 1) = '0'
BEGIN
SET #Result = SUBSTRING(#Result, 2, LEN(#Result) - 1)
END
-- Return the result of the function
RETURN #Result
END
GO
To remove the leading 0 from month following statement will definitely work.
SELECT replace(left(Convert(nvarchar,GETDATE(),101),2),'0','')+RIGHT(Convert(nvarchar,GETDATE(),101),8)
Just Replace GETDATE() with the date field of your Table.
To remove leading 0, You can multiply number column with 1
Eg: Select (ColumnName * 1)
select CASE
WHEN TRY_CONVERT(bigint,Mtrl_Nbr) = 0
THEN ''
ELSE substring(Mtrl_Nbr, patindex('%[^0]%',Mtrl_Nbr), 18)
END
you can try this
SELECT REPLACE(columnname,'0','') FROM table
I borrowed from ideas above. This is neither fast nor elegant. but it is accurate.
CASE
WHEN left(column, 3) = '000' THEN right(column, (len(column)-3))
WHEN left(column, 2) = '00' THEN right(a.column, (len(column)-2))
WHEN left(column, 1) = '0' THEN right(a.column, (len(column)-1))
ELSE
END
select ltrim('000045', '0') from dual;
LTRIM
-----
45
This should do.