I saw the following statement in a db patch:
ALTER TABLE tablename ADD PRIMARY KEY (somepk_columnname) USING INDEX;
I wanted to look up what USING INDEX does here, but only got from google, that it lets me specify some storage specific stuff, etc.
My question really is, what exactly happens here? Does the db use some default values here? Creates an index for the PK in the default tablespace? I thought that an index is created for every pk per default...
http://docs.oracle.com/cd/B28359_01/server.111/b28286/clauses002.htm#SQLRF52209
Using Indexes to Enforce Constraints
When defining the state of a unique or primary key constraint, you can
specify an index for Oracle to use to enforce the constraint, or you
can instruct Oracle to create the index used to enforce the
constraint.
using_index_clause You can specify the using_index_clause only when
enabling unique or primary key constraints. You can specify the
clauses of the using_index_clause in any order, but you can specify
each clause only once.
If you specify schema.index, then Oracle attempts to enforce the constraint using the specified index. If Oracle cannot find the index
or cannot use the index to enforce the constraint, then Oracle returns
an error.
If you specify the create_index_statement, then Oracle attempts to create the index and use it to enforce the constraint. If Oracle
cannot create the index or cannot use the index to enforce the
constraint, then Oracle returns an error.
If you neither specify an existing index nor create a new index, then Oracle creates the index. In this case:
The index receives the same name as the constraint.
If table is partitioned, then you can specify a locally or globally partitioned index for the unique or primary key constraint.
The response above was very helpful but I also wanted to use a specific tablespace for my unique key. This worked for me:
alter table tablename add constraint uk_name unique (col1, col2) using index tablespace tablespace_name;
Related
Having the following schema:
CREATE TABLE test_table(
cryptid varchar(255)
);
CREATE INDEX cryptid_index ON test_table (cryptid);
I am trying to a unique contraint to the column.
ALTER TABLE test_table ADD constraint crypid_unique_contraint UNIQUE(cryptid);
But this runs into an error:
Could not execute 'ALTER TABLE test_table ADD constraint crypid_unique_contraint ...'
Error: (dberror) [261]: invalid index name: column list already indexed
I can understand that the column is already indexed because I have created the index by myself. But I want the column to be unique. Is there a way to do this?
This is indeed an undocumented limitation in the current HANA versions.
The only way to create a unique constraint on this column is to first drop the single-column index present on this column.
I would consider the fact that this is not documented a (docu-)bug. However, the fact that existing indexes cannot be generally reused for uniqueness checks is not.
Single-column indexes in HANA's column store (which is what you use by default) tables are not B-tree indexes. Instead, these are inverted indexes into the column store structure of the main store-part of a column store table column.
These inverted structures cannot be checked for duplicates in the current transactional context as easily as B-tree indexes could.
This, I believe, is the reason for
a) implementing the uniqueness check only on a specific index implementation in the column store,
and
b) making the system behavior (not allowing the "conversion" of an existing index into a unique index) consistent across all table types.
As a general comment: for column store tables the benefit of single-column indexes for lookup/point-read scenarios is very often not worth the additional storage & compute resource consumption. This type of index practically doubles the memory requirement for the indexed column. So the speed-up in looking up a specific value should be worthwhile this additional permanent resource consumption.
You may check the documentation on INDEXES system view. They listed this index types:
Type of row store indexes: BTREE, BTREE_UNIQUE, CPBTREE, and CPBTREE_UNIQUE.
"Simple" index and unique index are a different index types at a build time, so there's no way to change it after the index was declared.
In other databases when you add unique constraint, it creates a new unique index (like in T-SQL or MySQL or Postgers) or reuses current index with this column (as in Oracle). But HANA doesn't allow you to create ether additional index on the same column (due to unknown reason, I didn't find it documented) or enforce constraint using existing index (due to poor implementation of mixture of uniqueness and index type).
The only way to go is to drop existing index and create it as unique (it is equivalent to unique constraint from the metadata point of view) from scratch, which you cannot due to authorizations. Sad but...
I am implementing functionality for a table that when an edit/change is made it will save a copy of the pre-edit row and mark it as is_deleted=TRUE, this is inorder to create a history of changes made to a row.
The email column in the table has a unique index which is preventing this functionality from being successful.
PostgreSQL said: duplicate key value violates unique constraint "users_email_unique"
Detail: Key (email)=(TEST) already exists.
Is there a way to apply the unique index only to rows that are marked is_deleted=FALSE, thus allowing for the changes to occur.
Since version 7.2, you can use partial indexes in PostgreSql
Add a where clause to the create index statement to make it a partial index:
CREATE UNIQUE INDEX users_email_unique ON tests (email)
WHERE NOT is_deleted; -- assuming is_deleted is Boolean
Though PostgreSql supports Alter index, from what I understand from the documentation the alter is limited to either rename or setting the tablespace.
This means that you will need to drop and re-create the index in order to change it into a partial index:
DROP INDEX users_email_unique;
CREATE UNIQUE INDEX users_email_unique ON tests (email)
WHERE NOT is_deleted; -- assuming is_deleted is Boolean
On one of my tables in SQL Server, In the Indexes folder I have a Clustered Index made from three columns of that table but there is also a Unique checkbox when I go to properties window on that index.
My question is with T-SQL commands how I tell it to drop the Uniqueness part and still keep the index? Is it even possible?
You cannot alter index from unique to non-unique. You can set index to ignore duplicates.
Docs: https://msdn.microsoft.com/en-us/library/ms188388.aspx
You can only recreate index with drop and create commands.
DROP INDEX IndexTest.ci_Test;
CREATE INDEX ci_Test ON IndexTest(Key);
But you should have clustered index on one column (for example on new autoincrement primary key). And you can force uniqueness with unique non-clustered index.
When export sql scripts by SQL Developer there are multiple options available, but either way there have to generate a UNIQUE INDEX on primary key like this
CREATE UNIQUE INDEX "SYS_C0018099" ON "TRANSACTION" ("ID")
and add PRIMARY KEY to the same table and same column
ALTER TABLE "TRANSACTION" ADD PRIMARY KEY ("ID")
So the question is: does it looks like kind of redundancy? I thought creating a primary key on a column should by default create an unique index on that column too? So why the first command is necessary?
And this may cause data redundancy?
I am on Oracle 11g so please share any ideas about why it should look like above.
Thanks in advance.
There is no redundancy - or only a little bit :)
The second command will use the index available if exists. Otherwise(if first DDL does not exists) will create an index.
The split into two commands is useful when you had given a proper name to the index and want to keep it.
UPDATE: The link indicated by Thomas Haratyk is a must read, I really like it: http://viralpatel.net/blogs/understanding-primary-keypk-constraint-in-oracle/
UPDATE2: a_horse_with_no_name is right, it can be done in a single statement like:
alter table TRANSACTION
add CONSTRAINT pk_test PRIMARY KEY (id);
So, it will keep the name(won't create a sysblalbla object name) and if you use the 'USING INDEX' keyword you can specify index atributes, for example storage atributes.
But again, you will not have any problems with those two statements, only an index is created.
Probably SQL Developer prefer to get a ddl per object and there might be cases when it's better its way.
I am using mySQL 5.1 and am wondering, is it necessary to add CREATE INDEX syntax on a column after you have defined it in a FK relationship. Common sense tells me that if a column is a key (foreign or otherwise), then it needs to be indexed - but you never know ...
Do I have to EXPLICITLY create an index on my FK - or does creating an FK implicitly creates an index on the column ?
Quoting this page of the MySQL manual : 13.6.4.4. FOREIGN KEY Constraints :
InnoDB requires indexes on foreign
keys and referenced keys so that
foreign key checks can be fast and not
require a table scan. In the
referencing table, there must be an
index where the foreign key columns
are listed as the first columns in the
same order. Such an index is
created on the referencing table
automatically if it does not exist.