How to rename an index in SQLite? - sql

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.

Related

Peewee create an index with type casting

I've looked around online and haven't been able to find a solution, but apologies if this question has been asked before.
I am trying to create an index on a jsonb column similar to the raw query:
CREATE INDEX idx ON table((jb_column::text));
where jb_column is the jsonb field.
I'm running into issues applying the index using the model class. I've tried mytable.add_index(SQL(CREATE INDEX idx ...)). While this does create the desired index, when I try to reset my database using the built-in model.delete().execute() functionality it fails to delete this index.
Therefore, I've also tried creating the index using more built-in peewee functionality. I have attempted:
idx = (mytable.index(
mytable.jb_column.cast('text')))
mytable.add_index(idx)
However, this does not create the desired index. Any advice?
Thank you :)
The problem is that this is the SQL evaluated by default (note the collision of the index names):
class MyTbl(Model):
data = BinaryJSONField()
MyTbl.add_index(MyTbl.index(MyTbl.data.cast('text')))
db.create_tables([MyTbl])
Produces:
CREATE TABLE IF NOT EXISTS "mytbl" (
"id" SERIAL NOT NULL PRIMARY KEY,
"data" JSONB NOT NULL)
CREATE INDEX IF NOT EXISTS "mytbl_data" ON "mytbl" USING GIN ("data")
CREATE INDEX IF NOT EXISTS "mytbl_data" ON "mytbl" CAST("data" AS text))
Solution - specify a name on our custom index:
idx = MyTbl.index(MyTbl.data.cast('text'), name='mytbl_data_text')
MyTbl.add_index(idx)
Solution 2 - do not use the default GIN index:
class MyTbl(Model):
data = BinaryJSONField(index=False) # GIN index won't be created.
... add custom index here ...

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

Conditional Index in DB2 database

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.

Fastest way to copy a table in mysql?

I want to copy a table in MySQL. What is the fastest way? Like this?
CREATE TABLE copy LIKE original;
INSERT INTO copy SELECT * FROM original;
or
CREATE TABLE copy SELECT * FROM original;
ALTER TABLE copy ADD PRIMARY KEY (id);
or is there another way?
EDIT: I'm worried about the indexes being re-created, how does mysql proceed executing these statements?
PS. can't use command-line tools like mysqldump, must be on-the-fly.
This copies the structure of the table immediately, but not the data:
CREATE TABLE copy LIKE original;
This creates all the indexes the original table had.
It works this way in mysql 5.1.39.
The fastest way using MyISAM tables while preserving indexes) and maybe other storage engines is:
CREATE TABLE copy LIKE original;
ALTER TABLE copy DISABLE KEYS;
INSERT INTO copy SELECT * FROM original;
ALTER TABLE copy ENABLE KEYS;
You want to disable your keys for your database load and then recreate the keys at the end.
Similarly, for InnoDB:
SET unique_checks=0; SET foreign_key_checks=0;
..insert sql code here..
SET unique_checks=1; SET foreign_key_checks=1;
(As pointed out in the comments.)
From the manual:
"CREATE TABLE ... SELECT does not automatically create any indexes for you. This is done intentionally to make the statement as flexible as possible. If you want to have indexes in the created table, you should specify these before the SELECT statement: "
CREATE TABLE bar (UNIQUE (n)) SELECT n FROM foo;
You can specify indices and data types (to avoid datatype conversion) in with both CREATE TABLE LIKE and CREATE TABLE SELECT. Which one is faster will depend on your setup.
To copy with indexes and triggers do these 2 queries:
CREATE TABLE newtable LIKE oldtable;
INSERT newtable SELECT * FROM oldtable;
To copy just structure and data use this one:
CREATE TABLE tbl_new AS SELECT * FROM tbl_old;
Does create table mynewtable (select * from myoldtable) work in mysql? If so you can try it too.
Best way to copy structure and all entries from one table to another table (by creating new table) is this query...
CREATE TABLE new_table LIKE old_table;
INSERT INTO new_table
SELECT * FROM old_table;
Try SELECT INTO, and use a variable as a go-between.
You'll have to create the receiving table, first, to have the same structure as the source table.
Best thing is, it's internal so it's fast. You'll lose your indexes, though.
if you are using MyISAM you can also copying and renaming the induvidual files .
.MYD, .MYI, .FRM files in the backend
Maybe you could take a look at SHOW CREATE TABLE.
Steps to take:
Go to phpmyadmin
Go to SQL
Execute this query
SHOW CREATE TABLE `the_old_table`;
Click options
Check "Full texts" and press Go.
The result is a full CREATE TABLE statement. Edit the query until you are happy.
Resource:
http://dev.mysql.com/doc/refman/5.7/en/show-create-table.html
CREATE TABLE copy SELECT * FROM original;
Is a fast way but maybe not the quickest cause of indexes.