Skip to Main Content

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Dennis.

Asked: September 01, 2004 - 9:07 am UTC

Last updated: January 27, 2005 - 11:01 am UTC

Version: 9.2.0.4

Viewed 1000+ times

You Asked

Tom,

This seems like a simple question, but I haven't figured it out yet. I am trying to use sql creating sql to build update statements for me, as we just got a new business requirement that all varchar2 columns should no longer have a NULL and should have a single space. While a not null constraint will solve the problem for future inserts, the existing data needs to be changed. What do you think the best approach would be? I originally coded

set echo off
set head off
set pagesize 0
set linesize 200
spool c:log.log
select 'update '||table_name||' set '||column_name||' = '' '' where '||column_name||' is null;'
from dba_tab_cols
where table_name = 'EMP' and
owner = 'SCOTT' and
data_type = 'VARCHAR2'
/
select 'commit;' from dual;
spool off

but realized that with large tables and maybe 80+ varchar2 columns in them, that may run out of undo. So I thought putting a commit after the update of each column would be wise, but I am having trouble making it be two distinct lines....unless you do not think the "non-printable" character at the end of the line will be a problem.

set echo off
set head off
set pagesize 0
set linesize 200
spool c:log.log
select 'update '||table_name||' set '||column_name||' = '' '' where '||column_name||' is null;'||chr(13)||chr(10)||'commit;'
from dba_tab_cols
where table_name = 'EMP' and
owner = 'SCOTT' and
data_type = 'VARCHAR2'
/
spool off


Should I worry about the linefeed/carriage return showing up in my spool file, or is there a way to strip that out in the select? Is there another method to get a line of update and a line of commit??

I was in the process of searching your site for "display results two lines" and "break results" (ooo I should try break output) when a question opened up. Currently, I'm trying something like this, but can't figure out how to make it return more than one row (emp has several varchar2 columns), and once that happens, avoid the duplicates from the union.

select CASE mod(rownum, 2)
when 1 then 'update '||table_name||' set '||column_name||' = '' '' where '||column_name||' is null;'
when 0 then 'commit;'
end
from (select rownum, table_name, column_name
from (select rownum, table_name, column_name
from dba_tab_cols
where table_name = 'EMP' and
owner = 'SCOTT' and
data_type = 'VARCHAR2')
UNION
(select rownum, table_name, column_name
from dba_tab_cols
where table_name = 'EMP' and
owner = 'SCOTT' and
data_type = 'VARCHAR2'))


I would appreciate any help you have to offer!

Thanks,
Dennis

and Tom said...

this is a horrible request from "the business".

man, what a mess you are heading towards. is that ' ' or ' ' or ' ' or ' ' in there.... I've a feeling the business wants to find "empty strings" fast but outlawing nulls is just "the wrong way to do it"

I would encourage you to encourage them that this is "a bad idea(tm)"

That aside, you want the CR/LF to "show up"? they would just show up as newlines. if this is windows, 13/10 is correct, if this is unix, just chr(10) is what you want.



but since this will be a simple sqlplus script, you could just


prompt set autocommit on
select 'update ....'



to have sqlplus autocommit after each statement.....

Rating

  (3 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Thanks!

Dennis, September 01, 2004 - 12:19 pm UTC

Yeah I wasn't thrilled either. They can check the data as it's going in to find out if it's null or not. I'll see if we can prod them to some other manner, but I've not been successful so far.

Thanks for the autocommit idea. That would the nice and simple way to do it! In my spool file, the chr(13)||chr(10) shows up (but then again I'm in Notepad...). It's probably a non-issue.

I think I can make it do the commits on a line if I make that a result set that I then pivot. I wasn't thinking of looking for pivot earlier. But that's if I decide not to do it the nice and simple way.

Thanks.


Line feeds show up in windows editor - sent over from Unix dbms_output script

j.register, January 27, 2005 - 10:34 am UTC

How do I keep linesize at a constant but remove line feed characters '^r' from unix file (generated by dbms_output in pl/sql script) before I send it to a windows file server?


Tom Kyte
January 27, 2005 - 11:01 am UTC

trick question I think.

\r is not embedded in the file on unix, \n is.

on windows, it would have \r\n

so, not really sure where the \r's are coming from?

Ravi, July 04, 2005 - 11:05 am UTC

How about this function to remove any lines from a variable that contain a matching pattern of characters.

/* Formatted on 2005/07/04 15:48 (Formatter Plus v4.6.6) */
CREATE OR REPLACE FUNCTION rm_lines_with_text (
full_text IN VARCHAR2 DEFAULT NULL,
search_text VARCHAR2 DEFAULT NULL
)
RETURN VARCHAR2
AS
text VARCHAR2 (4000) := full_text;
n NUMBER (10);
temptext VARCHAR2 (4000) := NULL;
BUILD VARCHAR2 (4000) := NULL;
filtered_text VARCHAR2 (4000) := NULL;
curr_line VARCHAR2 (4000) := NULL;
act_search_text VARCHAR2 (4000) := search_text;
BEGIN
LOOP
n := INSTR (text, CHR (10), 1);
curr_line := SUBSTR (text, 1, CASE
WHEN NVL (n, 0) = 0 THEN LENGTH (text)
ELSE n - 1
END);
filtered_text :=
filtered_text
|| CASE
WHEN INSTR (UPPER (curr_line), UPPER (act_search_text), 1) > 0 THEN NULL
ELSE curr_line || (CHR (10))
END;
temptext := SUBSTR (text, n + 1, LENGTH (text));
text := temptext;
EXIT WHEN (n IS NULL OR n = 0);
END LOOP;

RETURN (filtered_text);
END;
/