how to define full text searching on table with two keys? - sql-server

I have a table with 2 columns as primary key like below.
create table table1(key1 int NOT NULL,key2 int NOT NULL,content NVARCHAR(MAX), primary key(key1,key2))
I have created index on table with this query
CREATE unique INDEX index1 ON table1 (key1,key2);
and with this query, I create full-text searching
create fulltext index on table1 (content ) key index index1;
but I get this error because index must be single-column
'index1' is not a valid index to enforce a full-text search key. A full-text search key must be a unique, non-nullable, single-column index which is not offline, is not defined on a non-deterministic or imprecise nonpersisted computed column, does not have a filter, and has maximum size of 900 bytes. Choose another index for the full-text key.
and with single Column indexing, when I insert a new row I get a duplicate error.
what should I do?
I am using SQL Server and EF orm
Update
i solve this problem by creating a computed column that return unique data
ALTER TABLE Table1 ADD indexKey AS cast(key1 as float) + cast((cast(key2 as float)/power(10,len(key2))) as float) PERSISTED not null
and i create my index on this column and it work pretty fine.

Related

Database Index vs Primary Key

I want to start off saying I am not a database guru, but I'm decent with the basics.
I have a set of IO data that I'm storing in two tables which are uniquely identified by 'ioid' and 'machinenum'.
I have a 2 tables: IOConfig which uniquely identifies points (all the identifying information and a primary key: ConfigID). And a data table that contains samples of these items.
My table layouts below are to test using a primary key + index versus using just an index, so I know there is duplicate data.
Think of IOConfig table as such:
ConfigId(PK) machineNum ioId ioType
Think of IOData table as such:
Timestamp ConfigId machineNum ioId value
If I use the ConfigID primary key, with an index on (timestamp,ConfigId) my query is like this:
select * from AnalogInput
where sampleTimestamp>=1520306916007000000 and sampleTimestamp<=1520351489939000000
and configId in (1112)
"0" "0" "0" "SEARCH TABLE IOData USING INDEX cfgIndexAnalogInput (configId=? AND sampleTimestamp>? AND sampleTimestamp<?)"
If I avoid using ConfigID the query is like this:
select * from AnalogInput
where sampleTimestamp>=1520306916007000000 and sampleTimestamp<=1520351489939000000
and ioId in (1)
and machineid=1111
"0" "0" "0" "SEARCH TABLE IOData USING INDEX tsIndexAnalogInput (sampleTimestamp>? AND sampleTimestamp<?)"
Why wouldn't I get the improvement that I see with the first query + Index of (timestamp,configid) for the second query using an index of (timestamp,machineNum,ioid)? I ask because machineNum and ioid are used to define what point is unique to make a configId primary key... so one would expect them to equate?
schema:
CREATE TABLE 'IOData'(
'sampleTimestamp' INTEGER,
'configId' INTEGER,
'machineId' INTEGER,
'ioId' INTEGER,
'value' REAL);
CREATE TABLE 'IOConfig'(
'sampleTimestamp' INTEGER,
'configId' INTEGER PRIMARY KEY,
'machineId' INTEGER,
'ioId' INTEGER,
'ioType' INTEGER);
CREATE INDEX `Something` ON `IOData` (`sampleTimestamp` ASC,`machineId` ASC,`ioId` ASC)
CREATE INDEX cfgIndexAnalogInput ON IOData(configId,sampleTimestamp)
CREATE INDEX tsIndexAnalogInput ON IOData(sampleTimestamp)
Read Query Planning to understand how indexes work, and The SQLite Query Optimizer Overview to see what specific optimization will be applied.
In this case, the filter on sampleTimestamp uses inequality comparisons, so, according to section 1.0, that must be the last column in the index (either in an explicit index, or in a three-column primary key):
CREATE INDEX SomethingBetter ON IOData(machineId, ioId, sampleTimestamp);

Make Unique int column that allows NULLS in SSMS

How can I make an int column unique - on an existing table with data in - but allow multiple nulls - in SSMS.
There are many records in the table now - and they all have NULL in this column now.
I have seen ways to do this using a unique filtered index in TSQL - and I can see ways in the UI to do it without allowing NULLS.
Is this just not possible using the SSMS GUI?
As an aside what's the best way to do this just using pure TSQL? A unique filtered index?
With code:
create unique nonclustered index uixf_mycol
on dbo.t (col)
where col is not null;
In SSMS:
create a new nonclustered index by right clicking the index folder from
the expanded table in object explorer
add the column
check the unique checkbox
add the where clause in the filter panel.
You can create UNIQUE constraint on the column.
CREATE TABLE Test
(
P_Id int,
CONSTRAINT uc_ID UNIQUE (P_Id)
)

designing new table for daily uploads - use unique constraint

I am using SQL Server 2012 & am creating a table that will have 8 columns, types below
datetime
varchar(12)
varchar(6)
varchar(100)
float
float
int
datetime
Once a day (normally) there will be an upload of approx 10,000 rows of data. Going forward its possible it could be 100,000.
The rows will be unique if I group on the first three columns listed above. I have read I can use the unique constraint on multiple columns which will guarantee the rows are unique.
I think I'm correct in saying that the unique constraint by default sets up non-clustered index. Would a clustered index be better & assuming when the table starts to contain millions of rows this won't cause any issues?
My last question. By applying the unique constraint on my table I am right to say querying the data will be quicker than if the unique constraint wasn't applied (because of the non-clustering or clustering) & uploading the data will be slower (which is fine) with the constraint on the table?
Unique index can be non-clustered.
Primary key is unique and can be clustered
Clustered index is not unique by default
Unique clustered index is unique :)
Mor information you can get from this guide.
So, we should separate uniqueness and index keys.
If you need to kepp data unique by some column - create uniqe contraint (unique index). You'll protect your data.
Also, you can create primary key (PK) on your columns - they will be unique also. But, there is a difference: all other indexies will use PK for referencing, so PK must be as short as possible. So, my advice - create Identity column (int or bigint) and create PK on it. And, create unique index on your unique columns.
Querying data may become faster, if you do queries on your unique columns, if you do query on other columns - you need to create other, specific indexies.
So, unique keys - for data consistency, indexies - for queries.
I think I'm correct in saying that the unique constraint by default
sets up non-clustered index
TRUE
Would a clustered index be better & assuming when the table starts to
contain millions of rows this won't cause any issues?
(1)if u need to make (datetime ,varchar(12), varchar(6)) Unique
(2)if you application or you will access rows using datetime or datetime ,varchar(12) or datetime ,varchar(12), varchar(6) in where condition
ALL the time
then have primary key on (datetime ,varchar(12), varchar(6))
by default it will put Uniqness and clustered index on all above three column.
but as you commented above:
the queries will vary to be honest. I imagine most queries will make
use of the first datetime column
and you will deal with huge data and might join this table with other tables
then its better have a surrogate key( ever-increasing unique identifier ) in the table and to satisfy your Selects
have Non-Clustered INDEXES
Surrogate Key vs Business Key
NON-CLUSTERED INDEX

Can't delete primary key on table with FULLTEXT index

I have a table with a primary key that is an int data type. I want to drop this column (as it is unused, and I fear this column may reach the maximum limit of the int data type, so we may as well drop it.).
First, I could not drop I tried to first drop the constraint with:
ALTER TABLE dbo.MyTable DROP CONSTRAINT PK_MyTableID
I'm getting the error:
Cannot drop index 'PK_MyTableID' because it enforces the full-text key for table or indexed view 'MyTable'.
I don't understand this error, because the primary key is an int, and I don't think this table has a FULLTEXT index, but if it does, I don't need it.
EDIT:
I was able to drop the column after deleting the FULLTEXT index:
DROP FULLTEXT INDEX ON dbo.MyTable
I believe there is a full text index on the table. A full text index requires you to have unique key:
From MSDN: KEY INDEX index_name
Is the name of the unique key index on table_name. The KEY INDEX must be a unique, single-key, non-nullable column. Select the smallest unique key index for the full-text unique key. For the best performance, we recommend an integer data type for the full-text key.
You can check for a tables full text indexes using:
SELECT object_id, property_list_id, stoplist_id FROM sys.fulltext_indexes
where object_id = object_id('myTable');

Specifying the number of chars to be included in a compound index in T-SQL

I am reusing portions of a PostgreSQL schema in a SSQL database.
This is a snippet of my SQL statements:
CREATE TABLE pac_region
(id INTEGER NOT NULL PRIMARY KEY,
country_id INTEGER REFERENCES Country(id) ON UPDATE CASCADE ON DELETE NO ACTION,
name VARCHAR(256) NOT NULL
);
CREATE UNIQUE INDEX idxu_pac_region_name ON pac_region(country_id, name(32));
I want to specify that only the first 32 chars of the name need to be unique (when combined with the country_id).
SSMS barfs at the (32) specification. What is the correct way to restrict the length of a text used in a compound index, in TSQL?
I don't think you can create a index partially on a column, like what you are trying.
Rather, you can create a persisted computed column and add index on that column like
Taken from Create Index on partial CHAR Column
alter table pac_region
add Computed_Name as cast(name as varchar(32)) persisted;
CREATE UNIQUE INDEX idxu_pac_region_name
ON pac_region(country_id, Computed_Name);
(OR)
Probably by creating a indexed view.

Resources