Create index if not exist - oracle11g

ALL,
SQL> SELECT 1 FROM all_indexes WHERE table_name = UPPER( 'abcatcol' ) AND index_name = UPPER( 'abcatcol_tnam_ownr_cnam' );
no rows selected
SQL> CREATE INDEX abcatcol_tnam_ownr_cnam ON abcatcol(abc_tnam, abc_ownr, abc_cnam);
CREATE INDEX abcatcol_tnam_ownr_cnam ON abcatcol(abc_tnam, abc_ownr, abc_cnam)
*
ERROR at line 1:
ORA-01408: such column list already indexed
SQL> SELECT 1 FROM all_indexes WHERE table_name = UPPER( 'abcatcol' );
1
----------
1
SQL> SELECT index_name FROM all_indexes WHERE table_name = UPPER( 'abcatcol' );
INDEX_NAME
------------------------------
SYS_C007087
SQL >
What am I missing? Why can't I create an index?
EDIT:
SQL> select index_name, listagg(column_name, ', ') within group(order by 1)-- over(partition by index_name)
2 from dba_ind_columns
3 where table_name = 'ABCATCOL'
4 group by index_name;
INDEX_NAME
------------------------------
LISTAGG(COLUMN_NAME,',')WITHINGROUP(ORDERBY1)--OVER(PARTITIONBYINDEX_NAME)
--------------------------------------------------------------------------------
SYS_C007087
ABC_CNAM, ABC_OWNR, ABC_TNAM
SQL> SELECT index_name FROM all_indexes WHERE table_name = UPPER( 'abcatcol' );
INDEX_NAME
------------------------------
SYS_C007087
SQL>
EDIT2:
The suggested question utilizes PL/SQL. I want to understand how to do that using standard SQL and why my queries do not work as expected.
EDIT3:
This is the table definition:
CREATE TABLE abcatcol(abc_tnam char(129) NOT NULL, abc_tid integer, abc_ownr char(129) NOT NULL, abc_cnam char(129) NOT NULL, abc_cid smallint, abc_labl char(254), abc_lpos smallint, abc_hdr char(254), abc_hpos smallint, abc_itfy smallint, abc_mask char(31), abc_case smallint, abc_hght smallint, abc_wdth smallint, abc_ptrn char(31), abc_bmap char(1), abc_init char(254), abc_cmnt char(254), abc_edit char(31), abc_tag char(254), PRIMARY KEY( abc_tnam, abc_ownr, abc_cnam ));
So I guess since those fields are part of the PK Otacle already made the index, right?

You are looking for an index by it's name whereas oracle says to you this set of columns has been already indexed.
It means there is already an index with another name over that column set.
You need to check against dba_ind_columns table to get the index name over that column set
UPD. Here is the query to help you out to find the columns indexed
select index_name, listagg(column_name, ', ') within group(order by 1)-- over(partition by index_name)
from dba_ind_columns
where table_name = 'TABLE_NAME'
group by index_name;

Related

Insert Data into SQL Table with primary key column

I have a table in a SQL Server database and an R script that appends data to that tabl.
The db table contains a primary key ("ID"), which is just a scope_identity field
When I try to append the table into that location, I keep running into the following error
> sqlSave(Conn[["DbCon"]],
+ dat = OutputDataFinal,
+ tablename = "DataSci_StandardTransferPriority",
+ verbose = TRUE,
+ append = TRUE,
+ rownames = FALSE)
Query:
INSERT INTO "DataSci_StandardTransferPriority" (
"ID", "LeadSourceName", "AgeCategory", "ZipColor", "LeadCount_Sum",
"OB_TotalDials_Sum", "ContactRate", "TransferRate", "HypTransfers", "LaborCPT",
"MarketingCpt", "CloseRate", "PDLTR", "Policy_Count_Sum", "InboundDials_Sum",
"LeadCost_Sum", "PPT", "PPH", "ContactRateXCloseRate", "ContactRateXCloseRateTarget",
"ModelValue", "SourcePriority", "InsertTS"
)
VALUES ( ?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,? )
Error in odbcUpdate(channel, query, mydata, coldata[m, ], test = test, :
missing columns in 'data'
How can I append and ignore the issue with the primary key?
In standard INSERT operation dont specify identity column. It automatically provides next incremental identity value. For example:
CREATE TABLE #TempTable (
[ID] [bigint] NOT NULL IDENTITY(1, 1) PRIMARY KEY,
[Column1] [varchar](50) NULL,
[Column2] [decimal](19, 3) NOT NULL
);
INSERT INTO #TempTable (
[Column1],
[Column2]
)
VALUES
('first insert', 50.2),
('second insert', 84.2);
SELECT *
FROM #TempTable
DROP TABLE #TempTable;
The result was:
ID
Column1
Column2
1
first insert
50.200
2
second insert
84.200
If you want insert on identity column any way - enable IDENTITY_INSERT. But be care for data integrity issues.
CREATE TABLE #TempTable (
[ID] [bigint] NOT NULL IDENTITY(1, 1) PRIMARY KEY,
[Column1] [varchar](50) NULL,
[Column2] [decimal](19, 3) NOT NULL
);
INSERT INTO #TempTable (
[Column1],
[Column2]
)
VALUES ('first insert', 50.2);
SET IDENTITY_INSERT #TempTable ON;
INSERT INTO #TempTable (
[ID],
[Column1],
[Column2]
)
VALUES
(4, 'second insert', 84.63),
(2, 'third insert', 99.56);
SET IDENTITY_INSERT #TempTable OFF;
INSERT INTO #TempTable (
[Column1],
[Column2]
)
VALUES ('four insert', 100.32);
SELECT *
FROM #TempTable
DROP TABLE #TempTable;
And the result:
ID
Column1
Column2
1
first insert
50.200
2
third insert
99.560
4
second insert
84.630
5
four insert
100.320

Constraints about

What constraints are copied with table when we create table by using create table as select statement..?
I don't know about MySQL, but - as of Oracle - only the NOT NULL constraint. Even if there was a column designed as a primary key (which - implicitly - means that it can't be NULL), newly created table won't have that constraint.
For example:
SQL> create table test_1
2 (id number primary key,
3 name varchar2(20) not null);
Table created.
SQL> select constraint_name, constraint_Type from user_constraints where table_name = 'TEST_1';
CONSTRAINT_NAME C
-------------------- -
SYS_C009194 C --> "C"heck (NOT NULL) constraint
SYS_C009195 P --> "P"rimary key constraint
SQL> create table test_2 as select * from test_1;
Table created.
SQL> select constraint_name, constraint_Type from user_constraints where table_name = 'TEST_2';
CONSTRAINT_NAME C
-------------------- -
SYS_C009196 C --> that's the "C"heck - NOT NULL constraint
SQL> desc test_2
Name Null? Type
----------------------------------------- -------- ----------------------------
ID NUMBER
NAME NOT NULL VARCHAR2(20)
SQL>
MySQL would only preserve NOT NULL as constarint
CREATE TABLE tab1(id int AUTO_INCREMENT PRIMARY KEY)
create table tab2
(id int primary key,
col1 varchar(20) not null,
col2 int UNIQUE,
col3 int, FOREIGN KEY (col3) REFERENCES tab1(id))
CREATE TABLE tab3 AS SELECT * FROM tab2
Records: 0 Duplicates: 0 Warnings: 0
SHOW CREATE TABLE tab3
Table
Create Table
tab3
CREATE TABLE `tab3` (  `id` int NOT NULL,  `col1` varchar(20) NOT NULL,  `col2` int DEFAULT NULL,  `col3` int DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
fiddle

SQLite3 run a trigger insert multiple times besed on inserted vlaue

Want to run an insert n-times, the n is defined by inserted value on another table.
table 1:
create table Table1
(
id INTEGER default 1 not null
primary key
unique,
name TEXT not null
unique,
keys_number INTEGER default 1 not null
);
table 2:
create table table_2
(
id INTEGER default 1 not null
primary key
unique,
table_1_id INTEGER not null
references table_1,
);
Now when i insert into table_1 like:
INSERT INT table_1 (name, keys_number) VALUES ('dummy_name', 5)
want to run a trigger
CREATE TRIGGER insert_keys_after_insert_table_1
AFTER INSERT ON table_1
WHEN (SELECT COUNT(*) FROM table_2 WHERE table_1_id=new.id) < new.keys_number
BEGIN
INSERT INTO keys (table_1_id) VALUES (new.id);
END;
But this runs only once.
Finally, I want to have on table_2 values after the trigger
INSERT INT table_1 (name, keys_number) VALUES ('dummy_name_1', 5)
make the result like:
id;name;keys_number
1;dummy_name_1;5
and the result on table_2 after the trigger, should be
id;table_1_id
1;1
2;1
3;1
4;1
5;1
or if I insert another one on table_1
INSERT INT table_1 (name, keys_number) VALUES ('dummy_name_2', 2)
will make the result on table_1 like:
id;name;keys_number
1;dummy_name_1;5
2;dummy_name_2;2
and the trigger will give the result on table_2:
id;table_1_id
1;1
2;1
3;1
4;1
5;1
6;2
7;2
For this requirement you need a loop, which in SQL is implemented via a recursive CTE.
Unfortunately SQLite does not allow CTEs inside a trigger.
A workaround is to create a new table with only 1 column which will store the numbers 1 to the max expected value of keys_number in table_1:
CREATE TABLE table_numbers AS
WITH cte(keys_number) AS (
SELECT 1
UNION ALL
SELECT keys_number + 1 FROM cte WHERE keys_number < 100 -- change 100 to the max keys_number you expect
)
SELECT keys_number FROM cte
Now you can create your trigger:
CREATE TRIGGER insert_keys_after_insert_table_1 AFTER INSERT ON table_1
BEGIN
INSERT INTO table_2(table_1_id)
SELECT NEW.id
FROM table_numbers
WHERE keys_number <= NEW.keys_number - (SELECT COUNT(*) FROM table_2 WHERE table_1_id = NEW.id);
END;
See the demo.

Oracle PLSQL update table where in Associative Array?

I would like to, in a stored proc, update all the records that match an id.
Now, this list of id, is being passed in as a table of varchar (Associative Array)..
CREATE TYPE varcharArray AS TABLE OF VARCHAR2(1000) index by ...
and the proc declaration is something like
PROCEDURE testProc (p_IDs in varcharArray, p_Success out Number)
and the update statement in the proc
update testtable
set col = 'val'
where id in (select column_value from table(p_IDs);
This doesn't seem to work. So i had to do a loop in the array and update for each Id.
But i'd really like it to update using the where in clause.. Any help would be great.
PS: the id field is a number.
It works for me:
create table testtable (col varchar2(10), id varchar2(1000));
insert into testtable values (null, 'AAA');
insert into testtable values (null, 'BBB');
insert into testtable values (null, 'CCC');
insert into testtable values (null, 'DDD');
commit;
create or replace PROCEDURE testProc (p_IDs in varcharArray) is
begin
update testtable
set col = 'val'
where id in (select column_value from table(p_IDs));
end;
/
exec testproc(p_ids=>varcharArray('AAA','DDD'));
SQL> select * from testtable;
COL ID
---------- ----------
val AAA
BBB
CCC
val DDD

Select Record with Repeated Status using Sql Query

i have one Schedule Table like
i want to look like select query data is:
1 and 11 is Duplicate trainer and Duplicate day,time
10 and 12 is Duplicate trainer, Duplicate vanueid and Duplicate date,time
so last two column are display is not Duplicate than available and is Duplicate than display notavailable
Here is the solution that is coming to my mind.There may some syntax issue but i given the logic which may help you.
DECLARE #duplicate TABLE (
trainerId INT,
dt varchar(50)
)
INSERT INTO #duplicate SELECT TrainerId , [Date] from tbl GROUP BY TrainerId , Date HAVING (COUNT(*) > 1)
SELECT * FROM #duplicate
DECLARE #tempTable TABLE (
trainerId INT,
dt varchar(50),
status int
)
INSERT INTO #tempTable
SELECT trainerId , [Date] , STATUS = (SELECT COUNT(*) FROM #duplicate where trainerId = tbl.TrainerId and dt = tbl.Date) FROM tbl
![enter image description here][2]SELECT * , CASE [status] WHEN 0 THEN 'Available' ELSE 'Not Available' END FROM #tempTable

Resources