How to add new line character in DBMS_OUTPUT.put_line in LINUX - sql

In UNIX, in a SQL script, i have following code:
LOOP
DBMS_OUTPUT.put_line (p_key||'|'||p_loc||'\n');
END LOOP
Output is:
5482004|Dir/3-30-2017/file:47923.xml
5482009|Dir/3-30-2017/file:49288.xml
However in Linux, since "\n" doesn't work, i am replacing the above code with following code:
LOOP
DBMS_OUTPUT.put_line (p_key||'|'||p_loc);
DBMS_OUTPUT.new_line;
END LOOP
Output is:
20 5482004|Dir/3-30-2017/file:447923.xml 5482009|Dir/3-30-2017/file:449288.xml 5482010|Dir/3-30-2017/file:449739.xml 5482012|Dir/3-30-2017/file:45015.xml
The output in this format is without the new line after each line. Please suggest what is in correct in the loop.
P.S. I have also tried DBMS_OUTPUT.put_line (p_key||'|'||p_loc||chr(10)) but the output is still without the new line.

Please refer below SO answer for this question.
New Line Character in dbms_output

You can use chr(10)
My code in which i was trying to swap numbers ,where i need new line so i used chr(10)
DECLARE
A NUMBER;
B NUMBER;
TEMP NUMBER;
BEGIN
A:=&A;
B:=&B;
DBMS_OUTPUT.PUT_LINE(chr(10)||'BEFORE SWAP A is : '||A||' AND B is : '||B);
TEMP:=B;
B:=A;
A:=TEMP;
DBMS_OUTPUT.PUT_LINE(' AFTER SWAP A is : '||A||' AND B is : '||B);
END;
/
Output:
Enter value for a: 1
old 6: A:=&A;
new 6: A:=1;
Enter value for b: 2
old 7: B:=&B;
new 7: B:=2;
-- here i got new line
BEFORE SWAP A is : 1 AND B is : 2
AFTER SWAP A is : 2 AND B is : 1
PL/SQL procedure successfully completed.
So before line(i.e BEFORE SWAP A is : 1 AND B is : 2) in output i got new line.

Related

Getting ORA-10028 with DBMS_OUTPUT.PUT even with small chunk size?

I need to get a DBMS_OUTPUT that has an extensive length (60K+ characters). I understand the limit is 32767, but the issue for me with using the common LOOP solution...
LOOP
EXIT WHEN OUTPUT_OFFSET > DBMS_LOB.GETLENGTH(VAROUTT);
DBMS_OUTPUT.PUT_LINE(DBMS_LOB.SUBSTR(VAROUTT, OUTPUT_CHUNKS, OUTPUT_OFFSET));
OUTPUT_OFFSET := OUTPUT_OFFSET + OUTPUT_CHUNKS;
END LOOP;
... is that my string already contains new lines based on the calculation that is being done within the procedure. With PUT_LINE I'm getting the following (yellow) due to the PUT_LINE size:
So I need to make use of PUT, to ensure it's my procedure the one that determines when a NEW_LINE is to be inserted. I tried the following:
LOOP
EXIT WHEN OUTPUT_OFFSET > DBMS_LOB.GETLENGTH(VAROUTT);
DBMS_OUTPUT.PUT(DBMS_LOB.SUBSTR(VAROUTT, OUTPUT_CHUNKS, OUTPUT_OFFSET));
OUTPUT_OFFSET := OUTPUT_OFFSET + OUTPUT_CHUNKS;
END LOOP;
The only difference is that I'm calling command "PUT" instead of "PUT_LINE", to prevent my output from performing irrelevant new-line calls. The issue is that I'm getting error:
ORU-10028: line length overflow, limit of 32767 bytes per line.
This happens only if I use PUT instead of PUT_LINE, even if my chunk size is 10. My initial setup is:
SET SERVEROUTPUT ON SIZE UNLIMITED;
SET LINESIZE 200;
Not sure if the LINESIZE setup is relevant, still 200 is bigger than 10. Each line doesn't surpass 50 characters.
LINESIZE is a sqlplus parameter that wraps text in the display; it has no bearing on PL/SQL code.
By definition, DBMS_OUTPUT.PUT "places a partial line in the buffer." It doesn't matter how you set up your chunk size because you're just appending into the same 32K line limit. You must call DBMS_OUTPUT.NEW_LINE or DBMS_OUTPUT.PUT_LINE to introduce separate lines.
Note that DBMS_OUTPUT is generally used for debugging messages, and not large-scale text reporting.
my string already contains new lines
You can split your string on those newline characters (assuming each of those lines is then less than 32k, which seems to be the case - you said they're less than 50 characters each); i.e. varying OUTPUT_CHUNKS each time, and reading each chunk (minus its own newline) into a string buffer that you then print with put_line(). Something like:
...
BUFFER varchar2(32767);
...
WHILE OUTPUT_OFFSET < DBMS_LOB.GETLENGTH(VAROUTT) LOOP
-- read to next newline if there is one, rest of CLOB if not
IF dbms_lob.instr(VAROUTT, chr(10), OUTPUT_OFFSET) > 0 then
OUTPUT_CHUNKS := dbms_lob.instr(VAROUTT, chr(10), OUTPUT_OFFSET) - OUTPUT_OFFSET;
dbms_lob.read(VAROUTT, OUTPUT_CHUNKS, OUTPUT_OFFSET, BUFFER);
OUTPUT_OFFSET := OUTPUT_OFFSET + OUTPUT_CHUNKS + 1; -- skip newline character
ELSE
OUTPUT_CHUNKS := 32767;
dbms_lob.read(VAROUTT, OUTPUT_CHUNKS, OUTPUT_OFFSET, BUFFER);
OUTPUT_OFFSET := OUTPUT_OFFSET + OUTPUT_CHUNKS;
END IF;
dbms_output.put_line(BUFFER);
END LOOP;
You could store DBMS_LOB.GETLENGTH(VAROUTT) in a variable to avoid recalculating that thousands of times.

Need help in Reading contents of memory array and get a count in vhdl

input array: Ram = {D D D D D 3 3 3 3 7 7 7 9 9 8 8};
I am expecting the output as below:
Count = {0 0 0 4 0 0 0 3 2 2 0 0 0 5 0 0};
That is to count the number of occurances, like there are five D's , four 3's , three 7's, two 9's and two 8's so that Count array has 5 in Dth index, 4 in 3rd index, 3 in 7th index and so on.
my code is as below:
architecture behav of Bitcount is
signal cnt: count_type := (others=> (others=>'0'));
use ieee.numeric_std.all;
begin
Countproc:process(clk)
begin
if (clk'event and clk='1' ) then
if Enable='1' then
if (Read_bit='1') then
for k in 0 to 15 loop
for i in 0 to 15 loop
if ( Ram(k) = std_logic_vector(to_unsigned(i, 4)) )then
cnt(i) <= cnt(i) + "01";
end if;
end loop;
end loop;
end if;
end if;
Count <= cnt;
end if;
end process Countproc;
end behav;
but its not working as my expectation . pls help
Your problem is that cnt is a signal. It needs to be a variable.
The lines of code within a process are executed sequentially. Whenever a line of code containing a signal assignment (<=) is executed, an event is put on the event queue to drive the target signal (cnt in this case) on the next delta cycle (assuming there is some change to the target signal as a result). The event queue is the simulator's "to do" list; a delta cycle is one iteration of the simulator; the next iteration will occur once all the processes that are executing in the current iteration suspend.
If, during any execution of a process, another signal assignment to the same target signal is encountered, then (usually*) any other events on the event queue relating to that signal are deleted. So, in your example, every time this line is encountered (which it will be 16*16=256 times):
cnt(i) <= cnt(i) + "01";
Instead of incrementing cnt(i) (which is what I assume you are expecting to happen), all previous events relating to cnt(i) are deleted and replaced with a new event to drive cnt(i) with the value it had before the process started executing plus one. The signal cnt(i) does not get its new value until the process completes executed (and all other processes too).
Variables do not exhibit this behaviour; variables behave just like variables do in any software language. When a line of code is encountered with a variable assignment (:=), the variable is updated immediately and so its value is immediately available for further calculations.
So, how about changing cnt to a variable:
architecture behav of Bitcount is
use ieee.numeric_std.all;
begin
Countproc:process(clk)
variable cnt : count_type;
begin
if (clk'event and clk='1' ) then
if Enable='1' then
if (Read_bit='1') then
cnt := (others=> (others=>'0'));
for k in 0 to 15 loop
for i in 0 to 15 loop
if ( Ram(k) = std_logic_vector(to_unsigned(i, 4)) )then
cnt (i) := cnt (i) + "01";
end if;
end loop;
end loop;
Count <= cnt;
end if;
end if;
end if;
end process Countproc;
end behav;
I can't be sure this will work, because you haven't provided an MCVE, so I haven't tested it. But you original solution will not work for the reason I have given.
--
* this is nearly always true, because of the way that VHDL models delays as inertial delays and it is certainly true in this example. But strictly it's not always true.

SAS - # symbol in the INPUT statement

I have the following program, but don't understand what # symbol in the end of the INPUT lines does:
data colors;
input #1 Var1 $ #8 Var2 $ #;
input #1 Var3 $ #8 Var4 $ #;
datalines;
RED ORANGE YELLOW GREEN
BLUE INDIGO PURPLE VIOLET
CYAN WHOTE FICSIA BLACK
GRAY BROWN PINK MAGENTA
run;
proc print data=colors;
run;
Output produced without # in the end of the INPUT line is different from the ouput with #.
Can you please clarify what does # in the end of the 2nd and 3rd INPUT lines do?
# at the end of an input statement means, do not advance the line pointer after semicolon. ## means, do not advance the line pointer after the run statement either.
Normally an input statement has an implicit advance the line pointer one after semicolon. So:
data want;
input a b;
datalines;
1 2 3 4
5 6 7 8
run;
proc print data=want;
run;
Will return
1 2
5 6
If you want to read 3 4 into another line, then, you might do something like:
data want;
input a b #;
output;
input a b;
datalines;
1 2 3 4
5 6 7 8
run;
proc print data=want;
run;
Which gives
1 2
3 4
5 6
7 8
Similarly you could simply write
data want;
input a b ##;
datalines;
1 2 3 4
5 6 7 8
run;
proc print data=want;
run;
To get the same result - ## would hold the line pointer even across the run statement. (It still would advance once it hit the end of the line.)
In Summary: I think you probably don't want the trailing # in this case. The Input statements do not seem fitting for the data you are reading. With the trailing #, you are reading the same data into var1 and var3, and the same data into var2 and var4, because it is reading the same line twice. Either way, you are not reading in what the data appears to be. You would be better off with:
input Var1 $ Var2 $ #;
input Var3 $ Var4 $;
Or, more simply:
input Var1 $ Var2 $ Var3 $ Var4 $;
Official details from the SAS support site, annotated:
http://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/viewer.htm#a000146292.htm
Using Line-Hold Specifiers
Line-hold specifiers keep the pointer on
the current input record when
a data record is read by more than one INPUT statement (trailing #)
Use a single trailing # to allow the next INPUT statement to read from the same record.
Normally, each INPUT statement in a DATA step reads a new data record
into the input buffer. When you use a trailing #, the following
occurs:
The pointer position does not change.
No new record is read into the input buffer.
The next INPUT statement for the same iteration of the DATA step continues to read the same record rather than a new one.
SAS releases a record held by a trailing # when
a null INPUT statement executes:
input;
an INPUT statement without a trailing # executes
the next iteration of the DATA step begins.

Indentation of boxes in Format.fprintf

Please consider the function f:
open Format
let rec f i = match i with
| x when x <= 0 -> ()
| i ->
pp_open_hovbox std_formatter 2;
printf "This is line %d#." i;
f (i-1);
printf "This is line %d#." i;
close_box ();
()
It recursively opens hovboxes and prints something, followed by a newline hint (#.). When I call the f 3, i obtain the following output:
This is line 3
This is line 2
This is line 1
This is line 1
This is line 2
This is line 3
but I expected:
This is line 3
This is line 2
This is line 1
This is line 1
This is line 2
This is line 3
Can you explain why I obtain the first output and what I need to change to obtain the second one?
#. is not a newline hint, it is equivalent to print_newline which calls print_flush which closes all opened boxes and follows by a new line.
If you want to print line by line with Format you should open a vertical box with open_vbox and use print_cut ("#,") whenever you want to output a new line.
Instead of using #. you should use #\n specificator. The former, will flush the formatter and output a hard newline, actually breaking your pretty printing. It is intended to be used at the end of document, and, since it is not actually composable, I would warn against using it at all.
With #\n, you will get an output that is much closer to what you're expecting:
This is line 3
This is line 2
This is line 1
This is line 1
This is line 2
This is line 3
The same output, by the way, can be obtained by using vbox and emitting #; good break hints, that is better.

Invalid Input Exception Handling - SmallTalk

Let a smalltalk msg named "sum" return the sum of elements in an array.
Eg: #(1 2 3 4 5) sum ----> 15
When the input is #(1 2 'a' 3 5) sum. The execution terminates and shows a big exception box.
Instead of that how can we gracefully exit the execution by just showing a message. I don't want the big exception window to be shown.
sum
|sum|
sum := 0
self do: [:a | sum := sum + a]
^sum
I tried to handle the exception the below way. However, I notice that the execution doesn't terminate in case of invalid input.
sum
|sum|
sum := 0
self do: [:a |
(a isInteger) ifFalse:[
^[Error signal] on: Exception
do: [:ex | Transcript show: 'Entered values are non-numeric. Hence comparison is not possible.']
]
sum := sum + a
]
^sum
If the below code is placed in the workspace, I expected the execution to be terminated at line 2. However, line 3 is also getting executed.
|temp|
temp := #(1 2 3 'as' 4 5) sum.
temp := temp*5.
Changing the sum method to ignore the wrong types in the input Array does not make sense. Furthermore by replacing it with a UI message you completely loose control over what kind of input is acceptable. Rather deal with these exception at the place you use sum:
[ ^ self readInput sum ]
on: Error do: [ :error| Transcript show: 'Invalid input provided for sum' ].