10.27.2010

Row Count from all tables

This script will count the rows of all tables from a schema (prod).

 conn prod/pass

CREATE TABLE TABLECNT (TABLE_NAME VARCHAR2(40 CHAR), NUM_ROWS INTEGER);


declare row_cnt number;
begin 
for x in (select table_name from user_tables order by table_name) 
loop 
 execute immediate 'select count(*) from ' ||x.table_name into row_cnt; 
 insert into tablecnt values(x.table_name,row_cnt); 
 end loop;
end;
/
select * from TABLECNT order by NUM_ROWS desc;

10.21.2010

Q: How to Enable Archive Log?

When you enable this mode redo logs will be archived instead of overwritten. The archivelogs are stored in a seperate place usually can backed up regularly by your standard filesystem backup system. Archive logs are utilized by RMAN, Data Guard, Flashback and many others. If you are going to enable archivelog mode on a production database, I recommend shutting down the database and take a cold backup (Keeping a "final noarchivelog mode backup" which is to be a good and excepted practice).Enabling archive mode is simple, set the parameter LOG_ARCHIVE_DEST then connect to your database in mounted but closed mode (startup mount) and alter the database.

oracle@saturn:~$ echo $ORACLE_SID
DBTARGET

Connect as sysdba:
SQL> select LOG_MODE from v$database;
LOG_MODE
---------------------
NOARCHIVELOG

SQL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> startup mount
ORACLE instance started.
Total System Global Area 612368384 bytes
Fixed Size 2074664 bytes
Variable Size 180357080 bytes
Database Buffers 423624704 bytes
Redo Buffers 6311936 bytes
Database mounted.

SQL> alter database archivelog;
Database altered.

SQL> alter database open;
Database altered.

SQL> archive log list;
Database log mode Archive Mode
Automatic archival Enabled
Archive destination USE_DB_RECOVERY_FILE_DEST
Oldest online log sequence 5
Next log sequence to archive 7
Current log sequence 7
SQL> conn tnahar
Enter password:
Connected.

SQL> select LOG_MODE from v$database;

LOG_MODE
------------------------
ARCHIVELOG

SQL> show parameter log_archive_dest

NAME TYPE VALUE
------------------------------------ ----------------- ------------------------------
log_archive_dest string
log_archive_dest_1 string
log_archive_dest_10 string
log_archive_dest_2 string
log_archive_dest_3 string
log_archive_dest_4 string
log_archive_dest_5 string
log_archive_dest_6 string
log_archive_dest_7 string
log_archive_dest_8 string
log_archive_dest_9 string

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
log_archive_dest_state_1 string enable
log_archive_dest_state_10 string enable
log_archive_dest_state_2 string enable
log_archive_dest_state_3 string enable
log_archive_dest_state_4 string enable
log_archive_dest_state_5 string enable
log_archive_dest_state_6 string enable
log_archive_dest_state_7 string enable
log_archive_dest_state_8 string enable
log_archive_dest_state_9 string enable



SQL> alter system set log_archive_dest_1='location=/dump/DBTARGET_ARCHIVELOG/';

SQL> archive log list;Database log mode Archive Mode
Automatic archival Enabled
Archive destination /dump/DBTARGET_ARCHIVELOG/
Oldest online log sequence 5
Next log sequence to archive 7
Current log sequence 7

SQL>exit
Disable ARCHIVELOG Mode

Disabling archive mode is simple, connect to your database in mounted but closed mode (startup mount) and alter the database.
SQL> shutdown immediate;SQL> startup mountSQL> alter database noarchivelog; Database altered.SQL> alter database open; Database altered.

There are several system views that can provide you with information reguarding archives, such as:
V$DATABASE:
Identifies whether the database is in ARCHIVELOG or NOARCHIVELOG mode and whether MANUAL (archiving mode) has been specified.

V$ARCHIVED_LOG:
Displays historical archived log information from the control file. If you use a recovery catalog, the RC_ARCHIVED_LOG view contains similar information.

V$ARCHIVE_DEST:
Describes the current instance, all archive destinations, and the current value, mode, and status of these destinations.

V$ARCHIVE_PROCESSES:
Displays information about the state of the various archive processes for an instance.

V$BACKUP_REDOLOG:
Contains information about any backups of archived logs. If you use a recovery catalog, the RC_BACKUP_REDOLOG contains similar information.

V$LOG: Displays all redo log groups for the database and indicates which need to be archived.

V$LOG_HISTORY:
Contains log history information such as which logs have been archived and the SCN range for each archived log.


Basics about indexes in oracle

INDEX

Index provides a faster access path to table data.
 
Indexes are logically and physically independent of the data in the associated table. Being independent structures, they require storage space

You can create or drop an index without affecting the base tables, database, applications, or other indexes. 

The database automatically maintains indexes when you insert, update, and delete rows of the associated table. If you drop an index, all applications continue to work. However, access to previously indexed data might be slower.

Indexes in columns containing character data are based on the binary values of the characters in the database character set.

For a unique index, one rowid exists for each data value. 


For a nonunique index, the rowid is included in the key in sorted order, so nonunique indexes are sorted by the index key and rowid. Key values containing all nulls are not indexed, except for cluster indexes. Two rows can both contain all nulls without violating a unique index.

Oracle sometimes creates indexes for you. When you define a primary key constraint, Oracle will create an index for you. When you define a unique constraint, Oracle will also create an index for you.



Different Types of Index in Oracle

There are several types of index available for use in Oracle databases, the most common ones are B-tree (balanced tree) indexes, function-based indexes and bitmap indexes. B-tree indexes are more common in databases supporting OLTP systems and Bitmap indexes are more commonly used in data warehouses. 

1. Normal Index
By default, Oracle Database creates B-tree indexes/Normal index.

Ascending Index : default type
Descending IndexIf in the sql, first column always order by descending.

2. BITMAP Index
- Used in data warehouses
- Compact; work best for columns with a small set of values
- Where repeating values arise, bitmap would be a good choice in OLAP.

3. PARTITIONED Index
Partitioned index consist of partitions containing an entry for each value that appears in the indexed column(s) of the table. Types -

Global indexes
Local indexes

4. FUNCTION based Index
Which are based on expressions. They enable you to construct queries that evaluate the value returned by an expression, which in turn may include built-in or user-defined functions.


5. DOMAIN Index
Application-specific index.

6. CLUSTER Index
B-tree cluster indexes: defined specifically for cluster
Hash cluster indexes:  defined specifically for a hash cluster


There are more indexes like -
Key compressed Index
Reverse key index : Mostly useful for Oracle RAC applications
Index Organized Table



SYNTAX

Create Index
Create B-tree or default Index on single column -
CREATE INDEX emp_deptno ON empinfo (deptno); 
CREATE INDEX emp_deptno ON empinfo (deptno) TABLESPACE INDX02_16K; 

Multi column -
CREATE INDEX emp_seniority ON empinfo (deptno, hire_date); 

Unique Index -
CREATE UNIQUE INDEX dname_uix ON dept (dname);


Alter Index
Rebuilding Index - 
ALTER INDEX LB_SUBMITTER REBUILD;

Moving Index to a new tablespace -
ALTER INDEX test REBUILD TABLESPACE INDX02_16K;
 

Renaming Index -
ALTER INDEX SYS_C007109 RENAME TO LOGIN_ID; 

Quick-and-Dirty rebuild -
ALTER INDEX uniq_payroll_id COALESCE;

Dropping Index
DROP INDEX Index_name;  


 
Data dictionary Views for Indexes

ALL_INDEXES
SELECT INDEX_NAME, INDEX_TYPE, TABLE_OWNER, TABLE_NAME
FROM all_indexes 
WHERE TABLE_NAME='LOGIN';

USER_INDEXES
SELECT INDEX_NAME, INDEX_TYPE, TABLE_OWNER, TABLE_NAME
FROM user_indexes  
WHERE TABLE_NAME='NY_IP';

USER_IND_COLUMNS
SELECT * 
FROM user_ind_columns ic 
WHERE ic.table_name='LB_LOG_BOOK';

Linux Newbie

Q: How to zip file?

zip: nahar@mf01:~$ gzip df_prod_flexdoc_nahar_201001012.dmp
zip: nahar@mf01:~$ gunzip df_prod_flexdoc_nahar_20101012.zip


Q: How to zip folder?

zip -9 -r

Q: How to copy in current directory from Remote server?

scp remote_server_host_name:file_name.ext
nahar@debian:~$ scp remote_server_host_name:file_name.ext /home/nahar


Another example:
nahar@debian:~$ scp ms0001.thrp.net:/u/nahar/ds0003-ndstate-metadata1-20101104.dmp /home/nahar .


Q: How to find IP?

nahar@debian:~$ su
Password:
debian:/home/nahar# ifconfig

Q: How to change pass of oracle server?

passwd


Q: How to calculate file size?

du -sh

du -sh *.dmp

Q: How to move, copy file from one folder to another?

mv filename foldername/
or
cp old_file_name directory/new_file_name


Q: How to make unzip and untar folder?

tar -xvzf folder_name.tar.gz

Example-1:
file: tar -cvf 1_sylhet_boishak07_gram_picasa.tar sylhet_boishak07_gram_picasa
gzip 1_sylhet_boishak07_gram_picasa.tar

Example-2:
nahar@debian:~$ unzip oracle-script.zip
Archive: oracle-script.zip
replace 122.sh? [y]es, [n]o, [A]ll, [N]one, [r]ename: oracle
error: invalid response [o]
replace 122.sh? [y]es, [n]o, [A]ll, [N]one, [r]ename: r
new name: oracle
inflating: oracle
nahar@debian:~$

Another way -
1. To make ur that folder tar: tar -cvf new_folder_name.tar folder_name
2. To make your folder zip: gzip folder_name.tar"



STRAGG

This shows how to collect values from multiple rows into a single, comma delimited string. This is also known as "string aggregation".

I need to create this on "nddba" schema.

--------------------------- Comma Separated ----------------------------------------------
--========================================================

CREATE OR REPLACE TYPE nddba.stragg_type as object (
string varchar2 (4000),
static function ODCIAggregateInitialize
( sctx in out stragg_type )
return number ,
member function ODCIAggregateIterate
( self in out stragg_type ,
value in varchar2
) return number ,
member function ODCIAggregateTerminate
( self in stragg_type,
returnvalue out varchar2,
flags in number
) return number ,
member function ODCIAggregateMerge
( self in out stragg_type,
ctx2 in stragg_type
) return number
);
/


CREATE OR REPLACE TYPE body nddba.stragg_type
is
static function ODCIAggregateInitialize
( sctx in out stragg_type )
return number
is
begin
sctx := stragg_type( null ) ;
return ODCIConst.Success ;
end;
member function ODCIAggregateIterate
( self in out stragg_type ,
value in varchar2
) return number
is
begin
self.string := self.string || ',' || value ;
return ODCIConst.Success;
end;
member function ODCIAggregateTerminate
( self in stragg_type ,
returnvalue out varchar2 ,
flags in number
) return number
is
begin
returnValue := ltrim( self.string, ',' );
return ODCIConst.Success;
end;
member function ODCIAggregateMerge
( self in out stragg_type ,
ctx2 in stragg_type
) return number
is
begin
self.string := self.string || ctx2.string;
return ODCIConst.Success;
end;
end;
/

CREATE OR REPLACE FUNCTION nddba.stragg
(input varchar2 )
return varchar2
deterministic
parallel_enable
aggregate using stragg_type
;
/



--------------------------------
'br/' Separated ----------------------------------------------
--=======================================================


Step-1: Create STRAGG Type

CREATE OR REPLACE TYPE ndstate7.stragg_type as object
(
string varchar2(4000),

static function ODCIAggregateInitialize
( sctx in out stragg_type )
return number ,

member function ODCIAggregateIterate
( self in out stragg_type ,
value in varchar2
) return number ,

member function ODCIAggregateTerminate
( self in stragg_type,
returnvalue out varchar2,
flags in number
) return number ,

member function ODCIAggregateMerge
( self in out stragg_type,
ctx2 in stragg_type
) return number
);
/


Step-2:
BODY

CREATE OR REPLACE TYPE BODY stragg_type IS STATIC FUNCTION ODCIAggregateInitialize ( sctx IN OUT stragg_type )
RETURN NUMBER IS
BEGIN
sctx := stragg_type ( NULL );
RETURN ODCIConst.Success;
END;
MEMBER FUNCTION ODCIAggregateIterate ( self IN OUT stragg_type,value IN VARCHAR2 )
RETURN NUMBER IS
BEGIN
self.string := self.string || 'br/' || value;
RETURN ODCIConst.Success;
END;
MEMBER FUNCTION ODCIAggregateTerminate ( self IN stragg_type,returnvalue OUT VARCHAR2,flags IN NUMBER )
RETURN NUMBER IS
BEGIN
returnValue := ltrim ( self.string,'br/' );
RETURN ODCIConst.Success;
END;
MEMBER FUNCTION ODCIAggregateMerge ( self IN OUT stragg_type,ctx2 IN stragg_type )
RETURN NUMBER IS
BEGIN
self.string := self.string || ctx2.string;
RETURN ODCIConst.Success;
END;
END;
/




Step-3: Create
STRAGG Function

CREATE OR REPLACE FUNCTION ndstate.stragg
( input varchar2 )
return varchar2
deterministic
parallel_enable
aggregate using stragg_type
;
/

VVI: Have to add <> with all br/, in the single-quote.






10.19.2010

ORA-00054: resource busy and acquire with NOWAIT specified

Cause of the Problem:
Whenever you try to do any structural changes on a table oracle try to lock the table exclusively with NOWAIT option(this is in 10.2g while in 11g you can change the wait timeout). If oracle fails to lock the table exclusively then ORA-00054 will occur.

Solution of the Problem
In 10.2g you are limited to several choices to solve the problem. To avoid it-
-Re run the DDL at a later time when the database become idle.
-or, Kill the sessions that are preventing the exclusive lock.
-or, Prevent end user to connect to the database and then run the DDL.

Kill the sessions:
set long 30000
set lines 200 pages 200
col username format a20
col sess_id format a20
col mode_held format a20
col object format a30

SELECT oracle_username || ' (' || s.osuser || ')' username ,(s.sid || ',' || s.serial#) as sess_id
,s.STATUS "Session status"
,owner || '.' || object_name object,object_type
,decode( l.block,0,'Not Blocking',1,'Blocking', 2,'Global') status
,decode(v.locked_mode,0,'None',1,'Null',2,'Row-S (SS)',3,'Row-X (SX)',4,'Share',5,'S/Row-X (SSX)',6,'Exclusive',TO_CHAR(lmode)) mode_held
FROM v$locked_object v, dba_objects d, v$lock l, v$session s
WHERE v.object_id = d.object_id and v.object_id = l.id1 and v.session_id = s.sid
ORDER BY username, session_id;

SQL> alter system kill session '142, 232';

After killing all the locked sessions, I
connected to that schema where the row lock arise and press commit.

set lines 200 pages 200
col ses_serial format a30

Also have to see-
SELECT a.sid||','||a.serial# ses_serial,a.username,a.osuser
,to_char(a.logon_time, 'hh24:mi dd/mm/yy') login_time
FROM v$session a,v$process b
WHERE a.username IS NOT NULL AND a.paddr=b.addr AND a.type='USER'
AND a.logon_time> = sysdate- 1/48 --last 30 min
Order by a.sid,a.username;

Kill from OS level
select vs.sid, vs.username, vs.osuser, vs.process fg_pid,
vp.spid bg_pid
from v$session vs, v$process vp
where vs.paddr = vp.addr and vs.sid=319
order by vs.sid;

SID
---------- USERNAME ----------OSUSER ----------FG_PID ----------BG_PID
---------- ------------------------------ ------------------------------ ------------------ -----------------------------
319
-------------------------------------------oracle -------------17314 --------------17314

bash-3.00$ kill -9 17314



10.18.2010

Indexing SQLs for DBA

Q: How to check if indexes are used by an application or not?

select INDEX_NAME,INDEX_TYPE,TABLE_NAME 

from user_indexes 
where TABLE_NAME='LB_LOG_BOOK'; --SYS_C007158

To reset the values in the v$object_usage view, disable index monitoring and re-enable it:
ALTER INDEX LB_SUBMITTER NOMONITORING USAGE;
ALTER INDEX LB_SUBMITTER MONITORING USAGE;

SELECT table_name, index_name, monitoring, used FROM v$object_usage;

ANALYZE INDEX LB_SUBMITTER COMPUTE STATISTICS;


Q: Find out which Indexes are workable?

First of all, gather table statistics -

exec dbms_stats.gather_table_stats( ownname => 'PROD7',tabname => 'LB_LOG_BOOK', cascade => true);

Then
"Index Usage Count" column will show the index usage -
select p.object_name "Object Name",p.operation "Operation",p.options "Option"
, count(p.object_name) "Index Usage Count"
from dba_hist_sql_plan p, dba_hist_sqlstat s, dba_indexes di
where p.object_owner = 'PROD7'and p.operation like '%INDEX%'
and p.sql_id = s.sql_id and p.object_name = di.index_name and di.table_name='LOGIN'
group by p.object_name, p.operation, p.options
order by 1,2,3;



Q: which column for which index?

 
select * from user_ind_columns ic where ic.table_name='LOGIN';




Indexing on Foreign Key Referenced Columns

Non indexed Foreign key can lock child table(s)
when we need to delete from parent table.
This script will generate a log file from where we can find all referenced columns of a table (like-individual), and the "create index" script.

set pages 200 lines 200
SPOOL INDIVIDUAL_FK_INDEXING.sql

SELECT 'CREATE INDEX ' || a.table_name || '_' || c.column_name || '_I ON ' || a.table_name || '(' || c.column_name
|| ') ONLINE TABLESPACE INDX01_16K COMPUTE STATISTICS;'
FROM user_constraints a, user_constraints b, user_cons_columns c
WHERE a.r_constraint_name = b.constraint_name 

AND a.constraint_name = c.constraint_name
AND a.constraint_type='R' 

AND b.table_name='INDIVIDUAL';

SPOOL OFF;
 

We may need to change the index names if it crosses the maximum length for naming.
 


Finding the Non-Indexed Foreign Keys

COL table_name format A20 head 'TABLE_NAME'
COL constraint_name format A20 head 'CONSTRAINT_NAME'
COL table2 format A20 head 'TABLE_TO_BE_INDEXED'
COL column_name format A20 head 'COLUMN_TO_BE_INDEXED'



SELECT t.table_name,c.constraint_name,c.table_name table2,acc.column_name
FROM all_constraints t, all_constraints c, all_cons_columns acc
WHERE c.r_constraint_name = t.constraint_name
AND c.table_name =acc.table_name
AND c.constraint_name = acc.constraint_name
AND NOT EXISTS ( 
  SELECT '1' 
  FROM all_ind_columns aid
  WHERE aid.table_name = acc.table_name
  AND aid.column_name = acc.column_name
  )
AND t.table_name='CLIENT'
ORDER BY c.table_name; 


Partition Index rebuild - PL/SQL 

DECLARE
tab_name VARCHAR2(30);
stmt VARCHAR2(500);
sqlstr VARCHAR2(800);
TYPE TabCurTyp IS REF CURSOR;
ind_cursor TabCurTyp;
indx_name VARCHAR2(35);
part_name VARCHAR2(35);

BEGIN
tab_name := UPPER('&tab_name');
sqlstr:='SELECT distinct uip.index_name, uip.partition_name
FROM USER_IND_PARTITIONS uip, USER_TAB_PARTITIONS utp, USER_INDEXES ui
WHERE uip.partition_name= utp.partition_name
AND ui.index_name = uip.index_name
AND ui.table_name = utp.table_name
AND utp.table_name LIKE '''||tab_name||'%''';

OPEN ind_cursor FOR sqlstr;
LOOP
FETCH ind_cursor INTO indx_name,part_name;
EXIT WHEN ind_cursor%NOTFOUND;
stmt := 'ALTER INDEX ' || indx_name || ' REBUILD PARTITION ' ||part_name ||' ONLINE';
DBMS_OUTPUT.PUT_LINE(stmt);
EXECUTE IMMEDIATE stmt;
END LOOP;
END;
/

Here you only have to put the table name.


Single Syntax:
ALTER INDEX index_nm REBUILD PARTITION partition_name;

10.10.2010

How to make a Read Only Database User ?

Q: How to prevent any kind of DDL from any schema?

To prevent any kind of DDLs, this trigger will be stored on proper schema always and if any DDL issueed in the presence of the trigger, it will give us an error message.

CREATE OR REPLACE TRIGGER ddl_restrict_trigger
BEFORE ALTER OR CREATE OR DROP OR TRUNCATE
ON SCHEMA
BEGIN
RAISE_APPLICATION_ERROR(-20001,' You are not authorized to perform DDL. Please contact DBA Team.');
END;
/
Q: How to prevent any kind of DML from any table?

You can restrict the user on DML activity on tables other than select with a DML trigger. The following trigger won't allow to insert or delete or update on the table test.

create or replace trigger t1
before insert or update or delete on test for each row
begin
if inserting or updating or deleting then
raise_application_error(-20001,'Not Allowed');
end if;
end;

Q: STOP DML & DDL by making Sequence.

All tables are in nddba4@jupiter. I want to restrict the developers on DML activity on the data of nddba4. So am making another user nddba5. In nddba5, am making all the synonyms of the tables of nddba4 .
Now giving the devels access on nddba5. Here they only see the synonyms.

--fake user nddba5@jupiter, real user nddba4@jupiter
create user nddba5 identified by nddba5 default tablespace states;
grant connect, create synonym to nddba5;
grant select any table to nddba5;
grant select any dictionary to nddba5;

--at nddba5@jupiter, run this

SET SERVEROUT ON;
DECLARE
stmt varchar2(300);

BEGIN
FOR dr IN (select table_name from dba_tables where owner='NDDBA4')
LOOP

stmt := 'CREATE SYNONYM ' || dr.table_name || ' FOR NDDBA4.' || dr.table_name;
DBMS_OUTPUT.PUT_LINE(stmt);
EXECUTE IMMEDIATE stmt;
END LOOP;
END;
/

Notes

1. Constraints will not break when you rename tables.

2. You can back deleted datafiles but there is no guaranty that the object stored on the deleted datafile are available when it brought back

3. You can recover dropped tables by using FLASHBACK TABLE table_name TO BEFORE DROP;

4. Moving table to new tablespace will make all the indexes on the table unusable and prevent any DML activity on the table. Then you have to rebuild index.


10.08.2010

Update

Q: Update an existing table by adding a column, with a specific order?

I had a table(nd_osp_outcome) with data like -

OSP_ID ID DESCRIPTION RESPONSIBILITY
--- ------ ----------- ---------------
101 100 ddd rr
101 101 ddd rr
250 250 ddd rr
250 251 ddd rx
250 252 ddd rp
3100 3100 ddd rt
3100 3101 ddd ry

Have to update this like -

OSP_ID ID DESCRIPTION RESPONSIBILITY IDX
--- ------ ----------- --------------- ------
101 100 ddd rr 0
101 101 ddd rr 1
250 250 ddd rr 0
250 251 ddd rx 1
250 252 ddd rx 2
3100 3100 ddd rt 0
3100 3101 ddd ry 1

--
So, I am creating a temp table with the idx column -

CREATE TABLE temp_nd_osp_outcome AS
SELECT osp_id,id,rank()over ( partition by osp_id order by id) -1 idx
FROM nd_osp_outcome;

Then updating the existing table -

alter table nd_osp_outcome add idx number (10,0);

UPDATE nd_osp_outcome x
SET x.idx= (SELECT idx FROM temp_nd_osp_outcome y WHERE x.osp_id=y.osp_id AND x.ID=y.ID)
WHERE EXISTS (SELECT 1 FROM temp_nd_osp_outcome y WHERE x.osp_id=y.osp_id AND x.ID=y.ID);


select * from nd_osp_outcome order by osp_id,idx;

Q: Update records in one table based on values in another table?


alter table individual add constraint u_clnt_num_nd unique(CLNT_NUMBER_ND);

update (
select qer.INDIVIDUAL_ID, indv.id
from leg_qer qer, individual indv
where qer.client_number_nd = indv.clnt_number_nd )
set INDIVIDUAL_ID=id;


Q: How to add a Unique column on a table?

ALTER TABLE PROVIDER_SERVICE1 ADD PS_IDENTIFIER NUMBER(10);
UPDATE PROVIDER_SERVICE1 SET PS_IDENTIFIER=HIBERNATE_SEQUENCE.nextval;

Convert Varchar to Clob

desc feedback;

alter table feedback add (description2 clob);

update feedback set description2 = description;

alter table feedback drop column description;

alter table feedback rename column description2 to description;

desc feedback;

10.06.2010

Duplicate Row

Q: How to delete multiple duplicate row?

--Find out no of duplicate rows
select q.qtxt_identifier,count(*) as cnt from question_text q
group by q.qtxt_identifier having count(*)>1 order by q.qtxt_identifier; --54 duplicate rows found

select sum(cnt) from( select q.qtxt_identifier,count(*) as cnt from question_text q
group by q.qtxt_identifier having count(*)>1 order by q.qtxt_identifier)A; --113

--So, I have to delete 113-54=59 rows
--Delete duplicate rows
DELETE FROM question_text WHERE rowid NOT IN
(SELECT max(rowid) FROM question_text GROUP BY qtxt_identifier); --59 deleted



Q: I have 2 same rows in a table. All fields are same. I have to keep 1 and delete 1.


select * from client c where c.clnt_number =332096; --2 same rows returns
DELETE FROM client
WHERE rowid =
(SELECT MIN(rowid)
FROM client
WHERE clnt_number =332096);
commit;

select * from client c where c.clnt_number =332096; --1 row returns