Oracle:Set default value for number column - sql

How can we set default value for a number typed column has '00'?I tried this but it still saved it has '0',I need to do this.
//alter table table_name add column column1 default '00';
Please suggest a way for me.

You can store as number and when you retrieve do as
select column1,to_char(column2,'00') from mytable
SQL Fiddle Demo

It is not possible to store numbers like that - In a format you have described ('00'). You can store numbers as numbers (as values of numeric data type of course) and use to_char function or to_char function combined with lpad function to represent numbers in a format you like. Here is an example:
SQL> create table TB_SingleNumberColumn(
2 col number
3 )
4 /
Table created
SQL> insert into TB_SingleNumberColumn(Col) values(1);
1 row inserted
SQL> insert into TB_SingleNumberColumn(Col) values(5);
1 row inserted
SQL> insert into TB_SingleNumberColumn(Col) values(11);
1 row inserted
SQL> insert into TB_SingleNumberColumn(Col) values(111);
1 row inserted
SQL> commit;
Commit complete
-- The values as they are
SQL> select * from TB_SingleNumberColumn;
COL
----------
1
5
11
111
-- Values padded with zeros.
SQL> select to_char(col, '000') res
2 from TB_SingleNumberColumn;
RES
----
001
005
011
111
SQL> select lpad(to_char(col), 3, '0')
2 from TB_SingleNumberColumn
3 ;
LPAD(TO_CHAR(COL),3,'0')
------------------------
001
005
011
111

Related

How to compare similar data

I want to insert the data to PL-SQL.
But I need to check whether the table has similar Data.
If the table check has similar information, it cannot be added
exanple:
Insert Data : ABCD or ABCE
Table:
enter image description here
The Tabel Device has ABC,so it cannot be added.
How can I write this program?
You can use instr in plsql
example:
declare
x number;
begin
for i in (select distinct value from table)
loop
select count(1) into x
from table2
where instr(Device, i.value) > 0;
if (x = 0) then
insert into table2(Device) values(i.value);
end if;
commit;
end loop;
end;
Similar or the same data? That makes a huge difference. Because if you don't want the same data in your columns, you can just make the column unique. But if you want to check for similar data, welp, that's kind of hard to implement, hard to understand, and that just outright kills your performance...But if you still want to go that way, you can check out Jaro-Winkler Algorithm
Isi already mentioned the algorithm; here's an example of what you might be looking for.
Current table contents:
SQL> select * from test;
COL
-----
ABC
ABD
ABR
Here's how similar current values are to certain strings (ABCD, FDGH) you'd want to insert:
SQL> select t.col,
2 utl_match.jaro_winkler_similarity('ABCD', t.col) sim_abcd,
3 utl_match.jaro_winkler_similarity('FDGH', t.col) sim_fdgh
4 from test t;
COL SIM_ABCD SIM_FDGH
----- ---------- ----------
ABC 94 0
ABD 93 52
ABR 77 0
Now, it is up to you to decide which value will represent a limit and either insert a value into that table or not. Let's presume it is 90%. Then you'd
SQL> insert into test (col)
2 select '&&par_insert'
3 from dual
4 where 90 > (select max(utl_match.jaro_winkler_similarity('&&par_insert', a.col))
5 from test a
6 );
Enter value for par_insert: ABCD
0 rows created.
SQL>
Right; ABCD is similar to any of current values more than 90% and wasn't inserted.
How about FDGH?
SQL> undefine par_insert
SQL> /
Enter value for par_insert: FDGH
1 row created.
SQL> select * from test;
COL
-----
ABC
ABD
ABR
FDGH
SQL>
Yes, it was inserted.

How to text search in BLOB field

We have created a BLOB type column to store 6000 to 7000 ASCII characters of payload.
I am inserting the payload using following code.
PreparedStatement stmt=conn.prepareStatement(insertQuery);
String record="My ASCII Payload";
stmt.setBytes(1, record.getBytes());
stmt.execute();
When i run below query i can see the length of chars in the output.
select dbms_lob.getLength(MY_PAYLOAD)
from RAW_DATA;
6085
I wanted to perform text search in this BLOB column , i tried following options nothing works. What is the correct way to perform text search in a BLOB column ?
SELECT * FROM RAW_DATA t
WHERE dbms_lob.instr(t.MY_PAYLOAD,utl_raw.cast_to_raw(‘1234’))>0
select *
from RAW_DATA
where dbms_lob.instr (MY_PAYLOAD, -- the blob
utl_raw.cast_to_raw ('1234'),
1, -- where to start. i.e. offset
1 -- Which occurrance i.e. 1=first
) > 0
You can create text indexes on blobs as long as they contain text (naturally)
SQL> create table t ( x int, b blob);
Table created.
SQL>
SQL> insert into t values ( 1, utl_raw.cast_to_Raw('Hello there'));
1 row created.
SQL> insert into t values ( 2, utl_raw.cast_to_Raw('Goodbye tomorrow'));
1 row created.
SQL>
SQL> create index t_ix on t ( b )
2 indextype is ctxsys.context;
Index created.
SQL>
SQL> select x
2 from t where contains(b,'Hello') > 0;
X
----------
1
SQL>
SQL> select utl_raw.cast_to_varchar2(b)
2 from t
3 where contains(b,'Hello') > 0;
UTL_RAW.CAST_TO_VARCHAR2(B)
---------------------------------------------------------------------------------
Hello there

How to pass string data type to number datatype in plsql

I have procedure like this...
declare
v_psg varchar2(10);
id_no number;
begin
select value into v_psg from settings_am where key = 'PSG';
select id into id_no from product where to_char(psg) in (v_psg);
end;`
The value returned from select value into v_psg from settings_am where key = 'PSG'; would be
'1','2','3'
when i run this procedure i am returned with ora error - ORA-01403.
please advise how i should pass the v_psg value to psg column of product table?
EDIT - Tried with test case suggested
If you got ORA-01403, you were kind of lucky. It is the NO_DATA_FOUND error, which means that one (probably the first) query didn't return anything.
Those two statements could be combined into
select id
from product
where to_char(psg) in (select value
from settings_am
where key = 'PSG'
);
Why would you select value first, and then use it in another query? Besides, it just wouldn't work. v_psg is declared as VARCHAR2 variable. The way you described it, it contains the following string: '1','2','3', as if this is what you have:
SQL> create table settings_am (key varchar2(10),
2 value varchar2(20)); --> note size here
Table created.
SQL> insert into settings_am (key, value)
2 values ('PSG', q'['1','2','3']');
1 row created.
SQL> select * From settings_am;
KEY VALUE
---------- --------------------
PSG '1','2','3'
SQL>
As you can see, I enlarged the value column size, although variable you declared says 10. Why? Because of
SQL> select length(value) from settings_am where key = 'PSG';
LENGTH(VALUE)
-------------
11
i.e. you can't put something that is long 11 into something that accepts length 10.
Or, if your data actually contains 3 rows for the PSG key, are those values already enclosed into single quotes? If so, that's strange; people usually don't do that. Anyway, suppose that you managed to get string '1,2,3' (which is what I presume you actually have) into a VARCHAR2 variable, then you have to split it into rows in order to be able to use it in the IN clause:
SQL> create table product (id number, psg varchar2(10));
Table created.
SQL> insert into product (id, psg) values (100, '1');
1 row created.
SQL> insert into product (id, psg) values (200, '2');
1 row created.
SQL>
Query is then (where lines #3 - 5 represent splitting a string into rows):
SQL> select p.id
2 from product p
3 where p.psg in (select regexp_substr('&&v_psg', '[^,]+', 1, level)
4 from dual
5 connect by level <= regexp_count('&&v_psg', ',') + 1
6 );
Enter value for v_psg: 1,2,3
ID
----------
100
200
So, wouldn't it be simpler to use
SQL> select id
2 from product
3 where to_char(psg) in (select value
4 from settings_am
5 where key = 'PSG'
6 );
ID
----------
100
200
SQL>
Note that both options also show why your query is wrong: you can't put two values (rows) into a variable declared as id_no number; as you'd get TOO_MANY_ROWS error.
Finally, what is it that you'd want to do? What problem are you trying to solve? Apparently, except for special cases (only one row for each value) your query can't work. If you could provide test case (create table & insert into sample data), as well as expected output, it would be easier to help you.

How to make increment if same name occurs using triggers?

I have a table:
id
name
amount
If the same name was inserted, then amount should be incremented.
Else, insert with 0 amount.
How to create a trigger with a given condition?
You shouldn't really be doing that. AMOUNT column effectively counts number of NAME appearances in that table. You can always count it, can't you? So, what's the purpose of doing that?
If you want to know which name was inserted prior (or after) some other name (equal to the previous one), sort them by ID (if it is incremental, such as an identity column or if it gets its value from a sequence).
If ID isn't incremental, add DATE_INSERTED column (and sort by it; or apply ROW_NUMBER analytic function which orders values by DATE_INSERTED).
Also, what happens if you delete one of those duplicate names? Will you retroactively decrement AMOUNT column for all previous instances of that NAME?
But, if you insist, here's one option. As you can't just select from a table you're inserting into (because of the mutating table error), I'm using a compound trigger. The part of "insert amount 0" is done by setting the column's default value (you don't need any code for that).
SQL> create table test
2 (id number primary key,
3 name varchar2(20),
4 amount number default 0);
Table created.
SQL> create or replace trigger trg_ai_test
2 for insert on test
3 compound trigger
4
5 type test_rt is record (id test.id%type,
6 name test.name%type);
7 type rli_t is table of test_rt index by pls_integer;
8 g_rli rli_t;
9
10 after each row is
11 begin
12 g_rli(g_rli.count + 1).id := :new.id;
13 g_rli(g_rli.count).name := :new.name;
14 end after each row;
15
16 after statement is
17 l_cnt number;
18 begin
19 for i in 1 .. g_rli.count loop
20 dbms_output.put_Line('x');
21 dbms_output.put_line(i ||' '|| g_rli(i).id ||' '||g_rli(i).name);
22 select count(*) into l_cnt
23 from test
24 where name = g_rli(i).name;
25
26 update test set
27 amount = l_cnt
28 where id = g_rli(i).id;
29 end loop;
30
31 end after statement;
32 end trg_ai_test;
33 /
Trigger created.
SQL>
Testing:
SQL> insert into test (id, name) values (1, 'little');
1 row created.
SQL> insert into test (id, name) values (2, 'foot');
1 row created.
SQL> insert into test (id, name) values (3, 'little');
1 row created.
SQL> insert into test (id, name) values (9, 'little');
1 row created.
SQL> select * from test;
ID NAME AMOUNT
---------- -------------------- ----------
1 little 1
2 foot 1
3 little 2
9 little 3
SQL>
Or, a simpler solution (described above), without using that much code:
SQL> select id, name,
2 row_number() over (partition by name order by id) as amount
3 from test;
ID NAME AMOUNT
---------- -------------------- ----------
2 foot 1
1 little 1
3 little 2
9 little 3
SQL>

Autopopulating a column with a Trigger SQL

I'm trying to start a sequence that automatically populates a column when an insertion has been made. It should start from 500 and increment by 1. Any idea how would I go about doing this? So far I have something like this, but it seems to crash
CREATE TRIGGER ADD_TRIGGER ON tablename
AFTER INSERT
AS
BEGIN
ADD colname NUMBER IDENTITY(500,1);
END
GO
You can create a sequence
CREATE SEQUENCE mySeq
START WITH 500
INCREMENT BY 1
CACHE 100;
and then use it in your trigger
CREATE OR REPLACE TRIGGER myTrigger
AFTER INSERT ON table_name
FOR EACH ROW
BEGIN
SELECT mySeq.nextval
INTO :new.colname
FROM dual;
END;
Oracle 12c introduces IDENTITY COLUMNS.
SQL> CREATE TABLE new_identity_table
2 (
3 ID NUMBER GENERATED ALWAYS AS IDENTITY,
4 text VARCHAR2(50)
5 );
Table created.
SQL>
SQL> INSERT
2 INTO new_identity_table
3 (
4 text
5 )
6 VALUES
7 (
8 'This table has an identity column'
9 );
1 row created.
SQL> column text format A40;
SQL>
SQL> select * from new_identity_table;
ID TEXT
---------- ----------------------------------------
1 This table has an identity column
Oracle creates a sequence to populate the identity column. You can find it named as ISEQ$$
SQL> select sequence_name, min_value, max_value, increment_by from user_sequences;
SEQUENCE_NAME MIN_VALUE MAX_VALUE INCREMENT_BY
-------------------- ---------- ---------------------------- ------------
ISEQ$$_93199 1 9999999999999999999999999999 1
More more information about the identity columns, use the ALL_TAB_IDENTITY_COLS view.
SQL> SELECT table_name,
2 column_name,
3 generation_type,
4 identity_options
5 FROM all_tab_identity_cols
6 WHERE owner = 'LALIT'
7 ORDER BY 1, 2;
TABLE_NAME COLUMN_NAME GENERATION IDENTITY_OPTIONS
-------------------- --------------- ---------- --------------------------------------------------
NEW_IDENTITY_TABLE ID ALWAYS START WITH: 1, INCREMENT BY: 1, MAX_VALUE: 9999999
999999999999999999999, MIN_VALUE: 1, CYCLE_FLAG: N
, CACHE_SIZE: 20, ORDER_FLAG: N
For pre 12c releases, see Auto-increment primary key in Pre 12c releases (Identity functionality)