Conditional Index in DB2 database - indexing

Is there a possibility to create a conditional index in db2?
same as in oracle:
CREATE UNIQUE INDEX my_index ON my_table (
CASE WHEN my_column = 1
THEN indexed_column
ELSE NULL
END);
or mssql:
CREATE UNIQUE INDEX my_index
ON my_table (indexed_column) WHERE my_column = 1
Thanks :)

This looks like a contrived example, but I don't see any benefit of an index containing only the values 1 and NULL.
Expression-based indexes are supported beginning with DB2 LUW 10.5. If you are unable to upgrade, you can simulate the behaviour using a computed column (which is what Oracle does behind the scenes anyway).

The uniqueness is also checked during the execution of the CREATE
INDEX statement. If the table already contains rows with duplicate key
values, the index is not created.

Related

Why the indexes not speeding up the query?

I have the following query:
SELECT TOP 1000 *
FROM MyTable
WHERE Status = 'N' AND Type is not null
ORDER BY mytable.id
MyTable has 130 million rows.
I also created these indexes:
CREATE INDEX "MyTableIndex_1" ON MyTable (Status);
CREATE INDEX "MyTableIndex_2" ON MyTable (Type);
The ID column was already a clustered index.
Somehow the query is still very slow.
What am I missing?
try a multi column index
CREATE INDEX "MyTableIndex_StatusType" ON MyTable (Status, Type);
if that doesn't work then do some research on 'Covering Indexes'
Type is not null , the index on this column might not help.
BTW, can you try update index statistics before the query?

How to rename an index in SQLite?

In other databases such as MySQL I could just do this:
ALTER TABLE demo RENAME INDEX old_index TO new_index
What's the best workaround for SQLite?
Update
SQLite does not seem to support this syntax. In which case is there a work around I can use. For example:
DROP INDEX old_index;
CREATE INDEX new_index ON demo(col1, col2);
The issue with the above is that I need to manually find out which columns were indexed. I want something that can be done automatically like:
set columns = select columns indexed by old_index;
DROP INDEX old_index;
CREATE INDEX new_index ON demo(columns);
SQLite's ALTER TABLE does not support this. Just recreate it:
DROP INDEX old_index;
CREATE INDEX new_index ON demo([...]);
You can get the index definition from the schema:
SELECT sql FROM sqlite_master WHERE type = 'index' AND name = 'old_index';
But there is no mechanism to modify and execute the result from inside SQLite.

Create an INT index on a VARCHAR column

I have a unique design where I will need to store all data as VARCHAR. I can't go into details why. I would like to index some fields as a different data type. Is this possible? If so, will there any gotchas doing this? What is the syntax to do this if its possible.
I will be using both SQL Server and PostgresQL for this project.
In PostgreSQL, you can create functional indexes ("index on expression"), that occupies less storage than creating redundant columns.
CREATE INDEX tbl_intasvarchar_idx ON tbl (cast(intasvarchar AS int));
Keep in mind that queries have to match the expression to allow the use of such an index. Like:
SELECT *
FROM tbl
WHERE intasvarchar::int = 123;
(Alternative syntax shorthand for cast works as well as cast().)
Of course, all varchar values must be valid to cast to int and if that's the case the superior approach would be to change the type to integer to begin with. In any RDBMS.
PostgreSQL:
Create a function based index like so:
create index int_index on tbl (cast(cast(num_as_string as decimal) as integer));
Fiddle: http://sqlfiddle.com/#!15/d0f46/1/0
Later, when you run a query such as:
select *
from tbl
where cast(cast(num_as_string as decimal) as integer) = 12
The index will be used, because the index is on the result of that function applied to the column, rather than the column itself.
SQL Server:
In SQL Server you can add a computed column and index that computed column like so:
create table tbl (num_as_string varchar(10));
insert into tbl (num_as_string) values ('12.3');
alter table tbl add num_as_string_int as cast(cast(num_as_string as decimal) as integer);
create index int_index on tbl (num_as_string_int);
Then query against num_as_string_int to use the index.
Fiddle: http://sqlfiddle.com/#!6/1f378/2/0

drop unnamed contraints in access

I have a program with [msaccess] and i need rename the column of a table. The problem is that i can not rename with a sql statement if the column is indexed, so I have to delete the index.
To delete the index i use:
ALTER TABLE SuministroProductos DROP CONSTRAINT Index_84793306_29F5_4DFF
But not in all versions, does the index have the same name.
So, how can i know the name of the index in each table?
Is there another way of renaming the column? I need with SQL instructions in access.
Thank you
EDIT:
This work:
DROP INDEX Index_BB8ACAF4_28D7_4339 ON SuministroProductos
But this not work:
DROP INDEX Index_* ON SuministroProductos
The following code will iterate through the indexes of your table.
For i = 0 to CurrentDb.TableDefs("SuministroProductos").Indexes.Count - 1
IndexArray(i) = CurrentDb.TableDefs("SuministroProductos").Indexes(i).Name
Next

Practical limitations of expression indexes in PostgreSQL

I have a need to store data using the HSTORE type and index by key.
CREATE INDEX ix_product_size ON product(((data->'Size')::INT))
CREATE INDEX ix_product_color ON product(((data->'Color')))
etc.
What are the practical limitations of using expression indexes? In my case, there could be several hundred different types of data, hence several hundred expression indexes. Every insert, update, and select query will have to process against these indexes in order to pick the correct one.
I've never played with hstore, but I do something similar when I need an EAV column, e.g.:
create index on product_eav (eav_value) where (eav_type = 'int');
The limitation in doing so is that you need to be explicit in your query to make use of it, i.e. this query would not make use of the above index:
select product_id
from product_eav
where eav_name = 'size'
and eav_value = :size;
But this one would:
select product_id
from product_eav
where eav_name = 'size'
and eav_value = :size
and type = 'int';
In your example it should likely be more like:
create index on product ((data->'size')::int) where (data->'size' is not null);
This should avoid adding a reference to the index when there is no size entry. Depending on the PG version you're using the query may need to be modified like so:
select product_id
from products
where data->'size' is not null
and data->'size' = :size;
Another big difference between regular and partial index is that the latter cannot enforce a unique constraint in a table definition. This will succeed:
create unique index foo_bar_key on foo (bar) where (cond);
The following won't:
alter table foo add constraint foo_bar_key unique (bar) where (cond);
But this will:
alter table foo add constraint foo_bar_excl exclude (bar with =) where (cond);