Using substring in SQL update statement - sql

I'm writing a SQL query that updates the CUST_NAME column by appending the the word "CHECKED to it. The column is only 100 characters long however and I'm going to run into errors if I have an already long customer name and try appending CHECKED to it. So I want to use the Substring function in sql, but kind of stumped. I want to be able to substring the CUST_NAME field if it will go over 100 characters with the appended word. How can I do that?
Thank you
UPDATE CUST_INFO cust
SET CUST_NAME = (CUST_NAME||'_CHECKED')
WHERE process_timestamp = null;

Here is one way:
UPDATE CUST_INFO cust
SET CUST_NAME = SUBSTR(CUST_NAME, 1, 92) || '_CHECKED'
WHERE process_timestamp is null;
Also, if you want to update any records, then use is null rather than = null (the latter never evaluates to true).
Note: Not all databases have the left() function, you can use substr() or the equivalent instead.

Related

SQL Column Value Within string

I Have a string below
100Pipers22WoodfieldRoadBlackpoolFY16AX
I also have an address table on where i want to cross reference the postcode column to see if the value exists in the above string. Column value would be FY16AX which is visible in the string.
I cant seem to get a match.
If I understand correctly, you can use like. In standard SQL, this would look like:
where string like '%' || postcode
The || is the string concatenation operator. Some databases have their own operators or functions for this functionality.
Declare #vString nvarchar(50)
Set #vString = '100Pipers22WoodfieldRoadBlackpoolFY16AX'
Select Count(*) From tbl_Address Where Zip = right(#vString,6)
If the select statement returns a value greater than zero, you have a match.

assigning IS NULL to a string before querying DB

I have an excel spreadsheet with 15 or so fields. Wat I'm doing is, i open it, grab a row of data, then check each row for a value. Then using a few criteria I go look up to see if this Client value is already in the DB. As Example
Some of the fields mind be empty. Basically after checking some of the fields, I use them to check if that record exists already in DB. the problem arises when some fields are empty in which case when I query sql server it looks something like...
Select * from TblA where Company='Apple' and CompanyAdd ='Cupertino' and City=''
Because City = '' - it doesnt not find anything in SQL. The only thing that works is
and City is NULL
How am I able to programmatically assign that to a variable like CITY?
it is a string and the field in SQL is varchar
EDIT:
I want to be able to do something like this..... (as example)
if city = "" then
'I need this here to be so that....
city IS NULL
End if
So that when I query db it looks something like...
Select count(*) from TblA where City is Null
Is somethng like that possible?
You can use COALESCE for this purpose.
SELECT *
FROM TblA
WHERE COALESCE(Company, '')='Apple'
AND COALESCE(CompanyAdd, '') = 'Cupertino'
AND COALESCE(City, '') = ''
Keep in mind that the performance of this query will most likely not be stellar.

update a column using values from a different column of the same table

Given the DB table:
CREATE TABLE stuff (
id text not null,
other text
);
That has lots of id values but has all other set to NULL, is there an elegant way to update the table so that all other rows get updated to OTHER-{id} (where {id} is the value of the id column)?
(It must work in Postgresql)
Only a simple update statement is needed with some string concatenation (||):
update stuff
set other = 'OTHER-' || id
You'll want to use the following:
UPDATE stuff
SET other = 'OTHER-' || id;
UPDATE is the keyword used to identify which table you'd like to update.
SET is the keyword used to identify which column you'd like to update, and this is where you choose to assign the column to:
'OTHER-' || id
'OTHER-' being a string
|| a shorthand way to concatenate
id the value you want.
Another way of writing this would be
other = concat('OTHER-',id);
I along with many others will find the || method to be much cleaner, but it's worth knowing about the dedicated function as well.

Invalid Number Error! Can't seem to get around it

Oracle 10g DB. I have a table called s_contact. This table has a field called person_uid. This person_uid field is a varchar2 but contains valid numbers for some rows and in-valid numbers for other rows. For instance, one row might have a person_uid of '2-lkjsdf' and another might be 1234567890.
I want to return just the rows with valid numbers in person_uid. The SQL I am trying is...
select person_uid
from s_contact
where decode(trim(translate(person_uid, '1234567890', ' ')), null, 'n', 'c') = 'n'
The translate replaces all numbers with spaces so that a trim will result in null if the field only contained numbers. Then I use a decode statement to set a little code to filter on. n=number, c=char.
This seems to work when I run just a preview, but I get an 'invalid number' error when I add a filter of...
and person_uid = 100
-- or
and to_number(person_uid) = 100
I just don't understand what is happening! It should be filtering out all the records that are invalid numbers and 100 is obviously a number...
Any ideas anyone? Greatly Appreciated!
Unfortunately, the various subquery approaches that have been proposed are not guaranteed to work. Oracle is allowed to push the predicate into the subquery and then evaluate the conditions in whatever order it deems appropriate. If it happens to evaluate the PERSON_UID condition before filtering out the non-numeric rows, you'll get an error. Jonathan Gennick has an excellent article Subquery Madness that discusses this issue in quite a bit of detail.
That leaves you with a few options
1) Rework the data model. It's generally not a good idea to store numbers in anything other than a NUMBER column. In addition to causing this sort of issue, it has a tendency to screw up the optimizer's cardinality estimates which leads to less than ideal query plans.
2) Change the condition to specify a string value rather than a number. If PERSON_UID is supposed to be a string, your filter condition could be PERSON_UID = '100'. That avoids the need to perform the implicit conversion.
3) Write a custom function that does the string to number conversion and ignores any errors and use that in your code, i.e.
CREATE OR REPLACE FUNCTION my_to_number( p_arg IN VARCHAR2 )
RETURN NUMBER
IS
BEGIN
RETURN to_number( p_arg );
EXCEPTION
WHEN others THEN
RETURN NULL;
END;
and then my_to_number(PERSION_UID) = 100
4) Use a subquery that prevents the predicate from being pushed. This can be done in a few different ways. I personally prefer throwing a ROWNUM into the subquery, i.e. building on OMG Ponies' solution
WITH valid_persons AS (
SELECT TO_NUMBER(c.person_uid) 'person_uid',
ROWNUM rn
FROM S_CONTACT c
WHERE REGEXP_LIKE(c.personuid, '[[:digit:]]'))
SELECT *
FROM valid_persons vp
WHERE vp.person_uid = 100
Oracle can't push the vp.person_uid = 100 predicate into the subquery here because doing so would change the results. You could also use hints to force the subquery to be materialized or to prevent predicate pushing.
Another alternative is to combine the predicates:
where case when translate(person_uid, '1234567890', ' ')) is null
then to_number(person_uid) end = 100
When you add those numbers to the WHERE clause it's still doing those checks. You can't guarantee the ordering within the WHERE clause. So, it still tries to compare 100 to '2-lkjsdf'.
Can you use '100'?
Another option is to apply a subselect
SELECT * FROM (
select person_uid
from s_contact
where decode(trim(translate(person_uid, '1234567890', ' ')), null, 'n', 'c') = 'n'
)
WHERE TO_NUMBER(PERSON_UID) = 100
Regular expressions to the rescue!
where regexp_like (person_uid, '^[0-9]+$')
Use the first part of your query to generate a temp table. Then query the temp table based on person_uid = 100 or whatever.
The problem is that oracle tries to convert each person_uid to an int as it gets to it due to the additional and statement in your where clause. This behavior may or may not show up in the preview depending on what records where picked.

SQL replace old values with new ones

I have a table named tbl.Products, which has a column named articlenumber and is full of numbers like s401, s402, etc.
I generated a list with new article numbers which will replace the old ones:
s401 I00010
s402 I00020
s403 I00030
s403 I00040
...
I have a query from which I hoped that it would work out, but somehow it does nothing.
(of course I have nested the other values into the query)
SELECT REPLACE('articlenumber','s401','I00010') FROM tbl.Products
How do I get a query which replaces old values with new ones in a column like this?
Doing a replace can have problems (what if you have an articles s401 and s4010?), therefore it'll be more robust to do it like this:
Update tblProducts
SET articlenumber = 'I000010'
Where articlenumber = 's401';
If you have a number of changes to do, you can either generate a little script (for example with Excel, as TheButcher suggested), or you could import the data into a little table tblVals with the columns oldVal and newVal and then use this statement:
Update tblProducts p
SET articlenumber = (Select newVal
From tblVals
where oldVal = p.articlenumber);
This allows you to do the update in one statement which again will be more robust than running a script which may run into problems if it is really long.
A third idea would be to do the logic in constructing the new number for the old number (if such a thing exists) in SQL (or a Stored Procedure) like this:
Update tblProducts p
SET articlenumber = 'I0000' || Right(articlenumber,1) || '0'
(Of course this is totally simplified and probably not nearly sufficient for your 30k rows).
You are just selecting the newly replaced values and not doing anything with them... thats a very good idea when using replace, always select first to double check that you will get the expected result :)
The update code -
Update tbl.Products
Set articlenumber = replace(articlenumber, 's401', 'I00010')