Does table (string, string) require index? - sql-server

In my database running on SQL Server 2008 R2 I have a special table for global variables:
CREATE TABLE global_variables
(
name NVARCHAR(50),
value NVARCHAR(50) NOT NULL
CONSTRAINT PK_global_variables PRIMARY KEY CLUSTERED
(
name ASC
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
Does such table require indexing on value or not?

The primary key constraint creates an index (in this example, a clustered index) on the name column.
If you have queries that try to look up the name by giving the value, you'll need an index on value column to do that efficiently. Otherwise, if all of your lookups are based on name, you don't need to create an index on the value column.

Related

How do I insert a new record to a table containing just an IDENTITY column?

I have a single-column table where the column is a primary key and clustered index. It is used on other tables to relate records together. It doesn't seem an Insert statement is the way to go, there's no other columns to populate. It's a bit cumbersome to SET IDENTITY_INSERT off and on, etc.
I just need to "increment" the primary key of the table to the next integer value.
I believe it's an easy problem to solve, but I'm at that stage of mental exhaustion where the wheel is still spinning but the hamster is dead.
Here is a script to recreate the table I'm working with.
CREATE TABLE [dbo].[PKOnly]
(
[Id] [BIGINT] IDENTITY(1,1) NOT NULL,
CONSTRAINT [PK_PKOnly]
PRIMARY KEY CLUSTERED ([Id] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY];
You can use DEFAULT VALUES:
INSERT dbo.PKOnly DEFAULT VALUES;
Example db<>fiddle
Note this will also work if you have other columns with defaults.

How to make entity framework respect the true nature of default values on DB columns

Consider the following table definition which creates a table with default values which are not nullable and which have default values for when a value is not supplied
drop table [defaultTest]
CREATE TABLE [defaultTest](
[TestId] [int] IDENTITY(1,1) NOT NULL,
[TestData] [nvarchar](100) NOT NULL,
[TestKey] [int] NOT NULL,
[TestTimeStamp] [datetimeoffset](7) NOT NULL,
PRIMARY KEY CLUSTERED
(
[TestId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [defaultTest] ADD CONSTRAINT [DF_Test_TestKey] DEFAULT (NEXT VALUE FOR [SomeSequence]) FOR [TestKey]
GO
ALTER TABLE [defaultTest] ADD CONSTRAINT [DF_Test_TestTimeStamp] DEFAULT (sysdatetimeoffset()) FOR [TestTimeStamp]
GO
CREATE UNIQUE NONCLUSTERED INDEX [defaultTest_TestKey_Insert_UK] ON [defaultTest]
(
[TestKey] ASC,
[TestTimeStamp] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
declare #testkey int;
declare #id int;
insert into [defaultTest]([TestData]) values ('Original');
set #id = ##IDENTITY;
select #testkey = [TestKey] from [defaultTest] where [TestId] = #id;
insert into [defaultTest]([TestData], [TestKey] ) values ('Updated', #testkey);
select * from [defaultTest];
TestId TestData TestKey TestTimeStamp
1 Original 27 2019-06-26 14:40:22.1042605 +10:00
2 Updated 27 2019-06-26 14:40:22.1062673 +10:00
In the database this works perfectly. An insert can supply a value or not and the database will ensure that a value is always there.
But when this database table is referenced in entity framework database first i'm struggling to get entity framework to respect the true nature of the situation.
Observed behaviour is that it will either always pass zero values if StoredGeneratedPattern = none and the fields are empty and always pass null if StoredGeneratedPattern = Computed (or Identity) even if a value is supplied.
That is not how the definition ever works at the database level so why entity framework was programmed that way is a mystery?
Is there a way to get entity framework to behave properly for this scenario?
EDIT: I tried removing the not null constraint from the Key but entity framework refuses to pull the generated value back from the database.

Explicit conversion of column in Table Partition in SQL Server

I have table like below:
CREATE TABLE [dbo].[PartitionExample]
(
[dateTimeColumn1] [datetime] NOT NULL,
CONSTRAINT [PK_PartitionExample] PRIMARY KEY CLUSTERED
(
[dateTimeColumn1] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY =
OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
I have created Partition Function like below:
CREATE PARTITION FUNCTION DateRangePF (INT)
AS RANGE RIGHT FOR VALUES ( 20180601,20180901,20181201,20190301)
Then, I have created Partition Scheme for it:
CREATE PARTITION SCHEME DateRangePS
AS PARTITION DateRangePF TO
(FG032018_SampleDB,FG062018_SampleDB,FG092018_SampleDB,
FG122018_SampleDB,FG032019_SampleDB);
Now, When I am applying the partition scheme to this table, I want to apply explicit conversion of [dateTimeColumn1] column of datetime data type to INT Data Type. But when I tried it, I got syntax error:
ALTER TABLE [dbo].[PartitionExample] ADD
CONSTRAINT [PK_PartitionExample] PRIMARY KEY CLUSTERED
(
dateTimeColumn1 ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, ALLOW_ROW_LOCKS =
ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90)
ON DateRangePS(
convert(INT, CONVERT(CHAR(8), dateTimeColumn1, 112));
Can you guys please let me know
how explicit conversion can be implemented in such scenarios.
Also would it perform better when I will perform explicit conversion of datetime column or char(8) column to INT Column for partition.
Thank you for your help.

Add non-null unique constraint - not index

Basically I want to turn this:
ALTER TABLE [dbo].[Computer] ADD CONSTRAINT [AK_ResourceId] UNIQUE NONCLUSTERED
(
[ResourceId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
Into not affecting NULL values. The other posts only give an answer to make a unique index, but an index does not create violation when a duplicate value occurs on INSERT. I want a constraint, but I can't seem to make a WHERE statement on this..
Using SQL Server 2014
Update
It does work with an index after all :)
SQL:
CREATE UNIQUE NONCLUSTERED INDEX IX_ResourceId
ON dbo.Computer(ResourceId)
WHERE ResourceId IS NOT NULL;
This will create the following error:
Cannot insert duplicate key row in object 'dbo.Computer' with unique index 'IX_ResourceId'. The duplicate key value is (1234)

violation of primary key constraint in insert query not touching the PK column

I have a query that inserts record in a table. the primary key column of that table is an Identity field that auto-increments. the select part of the query will have duplicates, but I have an an unique constraint with ignore_dup_key=on on fields (city_nm, prov_en_nm) that should skip them on insert. this used to work fine, but for some reason now it gives me this message. this is the first time I try it since the database was moved from a 2012 sql server to a 2014 if that can have an impact
Violation of PRIMARY KEY constraint 'Dim_city_province_country_pk'. Cannot insert duplicate key in object 'HD_DtlClm.dim_city_province_country_t'. The duplicate key value is (###). (where ### is an ID, a different one every time I run it)
Here is the query.
INSERT INTO HD_DtlClm.[dim_city_province_country_t] (
city_nm, prov_en_nm, prov_fr_nm, contry_fr_nm, contry_en_nm
)
SELECT gr_mbr_city_nm, PROV_ENG_NM, PROV_FR_NM, CONTRY_ENG_NM, CONTRY_FR_NM
FROM isu.gr_dentl_clm_v
LEFT JOIN HD_DtlClm.province_information_t
ON gr_dentl_clm_v.gr_mbr_prov_cd = HD_DtlClm.province_information_t.PROV_CLM_CD
UNION
SELECT gr_prvdr_city_nm, PROV_ENG_NM, PROV_FR_NM, CONTRY_ENG_NM, CONTRY_FR_NM
FROM isu.gr_dentl_clm_v
LEFT JOIN HD_DtlClm.province_information_t
ON gr_dentl_clm_v.gr_prvdr_prov_cd IN (HD_DtlClm.province_information_t.PROV_ENG_CD, HD_DtlClm.province_information_t.PROV_CLM_CD)
Any idea why I get this error that I didn't get in the past?
EDIT to add primary key creation script:
ALTER TABLE [HD_DtlClm].[dim_city_province_country_t] ADD CONSTRAINT [Dim_city_province_country_pk] PRIMARY KEY CLUSTERED
( [cpc_key] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
EDIT2 to add table creation script
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [HD_DtlClm].[dim_city_province_country_t](
[cpc_key] [int] IDENTITY(1,1) NOT NULL,
[city_nm] [char](50) NOT NULL,
[prov_en_nm] [char](50) NULL,
[prov_fr_nm] [char](50) NULL,
[contry_en_nm] [char](75) NULL,
[contry_fr_nm] [char](75) NULL,
[create_ts] [datetime] NOT NULL,
[update_ts] [datetime] NOT NULL,
CONSTRAINT [Dim_city_province_country_pk] PRIMARY KEY CLUSTERED
(
[cpc_key] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
CONSTRAINT [dim_city_province_country_ak1] UNIQUE NONCLUSTERED
(
[city_nm] ASC,
[prov_en_nm] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = ON, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [HD_DtlClm].[dim_city_province_country_t] ADD DEFAULT (getdate()) FOR [create_ts]
GO
ALTER TABLE [HD_DtlClm].[dim_city_province_country_t] ADD DEFAULT (getdate()) FOR [update_ts]
GO
Try running: DBCC CHECKIDENT ('HD_DtlClm.[dim_city_province_country_t]'); look at the results returned in the messages tab & make sure the current identity value is equal to or higher than the current column value. NB running this may even fix the problem itself.
To expand: looks like something had reseeded your identity column, so the insert was causing duplicates to be picked up. Don't think there's any way to check historically what changed it; the most likely candidates are the DBCC CHECKIDENT command with RESEED option, or a TRUNCATE operation (will reseed to the original value).

Resources