SQL Server automatic naming of indexes when creating tables - sql-server

I'm rather new to SQL Server, (did learn SQL back in late 1980's, DB2 if I recall) Today I'm integrating my database layer into SQL, to begin with, SQL Server.
To begin with. As I do today, I will generate in runtime every databases objects, tables objects and indexes programmatically as I do with almost every visual and data object in my projects. That is, I use the visual designing tools very limited.
Every column in my project has a external description file's (every user has profile which contains these files), just as I do with database key's and for visual objects as for effect's as positioning, length, picture-mask, font size, etc. etc. i.e. dynamic forms. Almost every window, grids, filters is created in runtime just as far most of my database connections.
I did build a small test "machine" to create tables in this environment and did well, very easy to create tables within program (I use delphi and ADO)
The problem I encounter is when I flag a column as "autoincrement" or as Identity in SQL Server or if I describe a column as primary key, then SQL Server Management Studio creates automatically a index or key.
That would be ok if I could manage the name it gives this index or key.
Example of this situations:
AdoCommand.CommandText := Str_SQL;
TRY
AdoCommand.Execute;
FINALLY
NotiFy_TimeOut ('Table was created', wait_for_one_sec);
END;
My database engine creates this SQL script which I pass into the string Str_SQL above:
CREATE TABLE GENGITFL
(
NR INT NOT NULL IDENTITY,
GJM CHAR(3) NOT NULL,
HEITI VARCHAR(25) NOT NULL,
KAUPG REAL NULL,
SOLUG REAL NULL,
TOLLG REAL NULL,
DUMMY VARCHAR(20) NULL,
UNIQUE (GJM),
PRIMARY KEY (GJM)
)
SQL Server creates these two indexes automatically :
PK__GENGITFL__C51F17260A463F49
UQ__GENGITFL__C51F17277FA3E6E6
I don't want to use these names for these files, I would prefer names as:
IDX_GENGITFL_GJM
IDX_GENGITFL_NR
The reason should be obvious in light of my intro, the runtime engine can't create these names automatically and I consider it not a option to look for what index files are available within system database. If my external description say there should be index, I would like just to create names for the index automatically by using the prefix, IDX_ next the table name and last the field name or name's with underscore between, as IDX_GENGITFL_GJM etc.
Hope someone understand my poor english and presentation.. I'm rather rusty in english.
Thanks
Edit: After help from marc_s my SQL "script" is like this:
CREATE TABLE GENGITFL
(
NR INT NOT NULL IDENTITY,
GJM CHAR(3) NOT NULL,
HEITI VARCHAR(25) NOT NULL,
KAUPG REAL NULL,
SOLUG REAL NULL,
TOLLG REAL NULL,
DUMMY VARCHAR(20) NULL,
CONSTRAINT IDX_GENGITFL_NR UNIQUE (NR),
CONSTRAINT IDX_GENGITFL_GJM PRIMARY KEY (GJM),
)
CREATE INDEX IDX_GENGITFL_HEITI ON GENGITFL (HEITI)
Thanks again.

If you don't want the system default names - then just specify your own! :
CREATE TABLE GENGITFL
(
NR INT NOT NULL IDENTITY,
GJM CHAR(3) NOT NULL,
HEITI VARCHAR(25) NOT NULL,
KAUPG REAL NULL,
SOLUG REAL NULL,
TOLLG REAL NULL,
DUMMY VARCHAR(20) NULL,
CONSTRAINT IDX_GENGITFL_NR UNIQUE (GJM),
CONSTRAINT IDX_GENGITFL_GJM PRIMARY KEY (GJM)
)
See those CONSTRAINT (yourownnamehere) before the UNIQUE and the PRIMARY KEY ?
Now, your constraints are named as you defined.

Related

SQL Server - smart approach for combining GUID and identity column

I am trying to come up with a design for my database where across all my tables I'd like to have the combination of a GUID column (uniqueidentifier data type) and an identity column (int data type).
The GUID column is going to be a NONCLUSTERED index whilst the identity column is going to be the CLUSTERED index. I was wondering if the script below is a correct/safe approach when it comes to database design:
CREATE TABLE country
(
guid uniqueidentifier DEFAULT NEWID() NOT NULL,
code int IDENTITY(1, 1) NOT NULL,
isoCode nvarchar(5) NOT NULL,
description nvarchar(255) NOT NULL,
created date NOT NULL DEFAULT GETDATE(),
updated date NOT NULL DEFAULT GETDATE(),
inactive bit DEFAULT 0
CONSTRAINT NIX_guid PRIMARY KEY NONCLUSTERED(guid),
CONSTRAINT AK_code UNIQUE(code),
CONSTRAINT AK_isoCode UNIQUE(isoCode)
)
GO
CREATE UNIQUE CLUSTERED INDEX [IX_code] ON country ([code] ASC)
GO
That's how it looks after running the above script:
Any tips would be much appreciated!
The domain of all possible countries is never going to be more than a few hundred, so performance should not be a concern.
You already have an isoCode. That is a canonically defined candidate key. I understand what you mean when talking about GUIDs being useful because they can never collide when created on separate servers/application instances/etc. But ISO country codes can never collide either, because they're already defined by an external authority. You don't need the GUID.
Why is your existing isoCode column an nvarchar(5)? There is a 2 letter, and a 3 letter, ISO3166 standard. There are no unicode characters required, so you can use char(2) or char(3) depending on which standard you pick, both of which would be narrower than a 4 byte int.
Yes, an identity-based clustered index does mean not having to worry about page splits on insert. But these are countries. We already know all of the countries you need to insert right now, and are you really worried that the handful of changes that might be made over the next few decades will kill the performance of your system due to page splits on insert? No, so you don't need the identity column either.
Eliminate both surrogates, and just go with the alpha-2 or alpha-3 ISO country code as your clustered primary key.

Feedback on database table structure for queue containing arbitrary tasks

I want to introduce a queue functionality in an existing application built on Access VBA with an SQL Server 2012 backend. It should allow the application to store open tasks with 1:n parameters in a queue table and process them later on. It deserves mentioning that for some tasks, it might take several process steps until all information needed for their processing is available.
Some more information on my current situation:
The data needs to be persisted in the database for compliance reasons
No more than 1500 tasks will be processed each day
The application will be rebuild (except for the backend), the new application will make much more heavy use of this queue functionality
The total number of different tasks to be queued, as well as the no. of parameters they might need, is unknown
My currently best approach - however in EAV schema - would consist of three tables:
1. Table "tblQueueItemType"
It contains definitions for each type (or category) of task.
It contains an id, a name and an attribute count. This attribute count defines the number of attributes for this task. I want to use it later on to ensure data consistency for all tasks with status "READY".
Example for an entry in this table:
"1", "Generate Book Database Entry", "5"
2. Table "tblQueueItemHeader"
It which represents the instantiated tasks defined in the tblQeueItemType. They have a task id, their corresponding task type defined in tblQeueItemType, a status as well as a timestamp.
The status is either OPEN (not all information available), READY (all information available to process task), and DONE (when processed).
Example for an entry in this table:
"2", "1", "OPEN"
3. Table "tblQueueItemAttribute"
It contains all the information the tasks need to be processed. It contains an id, the id of the header, an attribute type and an attribute value.
Example entries for this table:
"1","2", "Author", "H.G. Wells"
"1","2", "No. Pages", "1234"
My table definitions so far:
CREATE TABLE [dbo].[tblQueueItemType](
id INT NOT NULL IDENTITY (1,1) PRIMARY KEY,
Name NVARCHAR(20) NOT NULL,
AttributeCount INT NOT NULL
)
CREATE TABLE [dbo].[tblQueueItemHeader](
id INT NOT NULL IDENTITY (1,1) PRIMARY KEY,
QueueItemTypeId INT NOT NULL,
Status NVARCHAR(5) NOT NULL,
Timestamp DATETIME NOT NULL
CONSTRAINT QueueTypeHeader
FOREIGN KEY (QueueItemTypeId)
REFERENCES tblQueueItemType (id)
)
CREATE TABLE [dbo].[tblQueueItemAttribute](
id INT NOT NULL IDENTITY (1,1) PRIMARY KEY,
QueueItemHeaderId INT NOT NULL,
Attribute NVARCHAR(5) NOT NULL,
Value NVARCHAR(50) NOT NULL,
Timestamp DATETIME NOT NULL
CONSTRAINT QueueHeaderAttribute
FOREIGN KEY (QueueItemHeaderId)
REFERENCES tblQueueItemHeader (id)
)
ALTER TABLE tblQueueItemHeader
ADD CONSTRAINT QueueItemHeaderStatus
CHECK (Status IN ('OPEN', 'READY', 'DONE'));
Obviously the current design is suboptimal. What would be best schema for this kind of use-case? How feasible is my current approach?
Thank you very much!

Access to SQL link table showing Allow Zero Length as 'Yes'

I have made multiple attempts at creating a SQL Server table to link to an Access front-end with 'disallow zero length value' constraints on the table but when I link the table up to my front-end the design of the table shows Allow Zero Length = Yes
Now I have tried various methods of trying to change this to No (I need it to be No for a migration project I am working on). I am not sure what needs to be done on the SQL Server to ensure that upon linking this table to my access front-end, this constraint is a No.
This is the Create script for my table:
Create Table Riku(
ID int NOT NULL PRIMARY KEY,
testtext varchar(255),
CONSTRAINT DissalowNulls
CHECK (testtext <> ''),
CONSTRAINT DissalowNull2
CHECK (LEN(testtext) = 0)
);
Neither of these two constraints work. I have tried using Nvarchar, Varchar, and Text as SQL Data Type all of which yielded this same result (Yes).
Any ideas?
You must indicate to the column that does not allow null
Create Table Riku(
ID int NOT NULL PRIMARY KEY,
testtext varchar(255) NOT NULL,
CONSTRAINT DissalowNulls
CHECK (testtext <> '')
);
I am interpreting your question as:
"Why is it when I create a constraint in SQL Server to 'DisalowNulls'
does it not appear that way when viewing the table properties in
Access?"
My answer to that questions is, "they are not syntax equivalent features". When Access interprets the design of the linked table it is not perceiving these as the same property. The constraint you created in SQL Server is more equivalent to an Access Validation Rule although that will also not appear in the Access table designer.
It would be nice if Access would disable properties that aren't relevant to the database type of the linked table. Other properties like Format, Input Mask, and Caption could also be in that category.

Memory Optimized Tables + Encryption and Identity Column

I was wondering whether it is possible to have a always encrypted Memory Optimized Table and also have its Primary Key automatically seeded? For example, I want to create the following:
CREATE TABLE Foo
(
[Id] [int] Identity(1,1) NOT NULL,
[Bar] NVARCHAR(MAX) NOT NULL,
CONSTRAINT [PK_Foo] PRIMARY KEY NONCLUSTERED ([Id] ASC)
)
WITH (MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_ONLY)
GO
Fairly simple table and is initially created fine however, when I attempt to encrypt the column Bar I get the following exception.
Apr 21 2017 09:23:00 [Error] WorkitemExecution: Message:Inner
exception: System.Data.SqlClient.SqlException Details: Cannot insert
explicit value for identity column in table 'Foo' when IDENTITY_INSERT
is set to OFF..
I also tried setting SET IDENTITY_INSERT Foo ON after the create table statement but still no luck.
Reading the documentation as well doesn't seem to suggest this isn't possible but perhaps I have missed something? If this isn't possible I have another approach which I know will work.
I guess my question in summary is.. "do Memory Optimized Tables support always encrypted with an identity column".
You cannot encrypt identity columns using Always Encrypted, regardless if they are stored in memory optimized tables or in regular tables. In the normal Always Encrypted query processing flow, values inserted into encrypted columns are created and encrypted on the client-side. Note that only the client has encryption keys and can encrypt/decrypt data. SQL Server, by design, does not have access to encryption keys and cannot perform cryptographic operations.Identity column values are generated on the server side, so they do not fit the above workflow.
It would be useful to understand why you are trying to encrypt your identity column. Always Encrypted is designed to be used for protecting sensitive data. Auto-generated identifiers are typically not considered to be sensitive information.
Thanks,
Jakub
Even after your encryption through wizard failed, you should have a CMK and CEK created for you. You can check the name of the CEK that was created by browsing to YourDb -> Security -> Always Encrypted Keys -> Column Encryption Keys in SSMS object explorer. In my case the name of CEK was CEK_Auto1
If you find that there are no Column Encryption Keys in the above location, you can create new one by following the steps outlined in Provisioning Column Master Keys (New Column Master Key) and Provisioning Column Encryption Keys (New Column Encryption Key) in this article
You should be able to create the table as follows
CREATE TABLE Foo
(
[Id] [int] Identity(1,1) NOT NULL,
[Bar] NVARCHAR(MAX) COLLATE Latin1_General_BIN2 ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = [CEK_Auto1], ENCRYPTION_TYPE = Deterministic, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256') NULL,
CONSTRAINT [PK_Foo] PRIMARY KEY NONCLUSTERED ([Id] ASC)
)
WITH (MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_ONLY)
GO

Large sample database for HSQLDB?

I'm taking a database class and I'd like to have a large sample database to experiment with. My definition of large here is that there's enough data in the database so that if I try a query that's very inefficient, I'll be able to tell by the amount of time it takes to execute. I've googled for this and not found anything that's HSQLDB specific, but maybe I'm using the wrong keywords. Basically I'm hoping to find something that's already set up, with the tables, primary keys, etc. and normalized and all that, so I can try things out on a somewhat realistic database. For HSQLDB I guess that would just be the .script file. Anyway if anybody knows of any resources for this I'd really appreciate it.
You can use the MySQL Sakila database schema and data (open source, on MySQL web site), but you need to modify the schema definition. You can delete the view and trigger definitions, which are not necessary for your experiment. For example:
CREATE TABLE country (
country_id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
country VARCHAR(50) NOT NULL,
last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (country_id)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
modified:
CREATE TABLE country (
country_id SMALLINT GENERATED BY DEFAULT AS IDENTITY,
country VARCHAR(50) NOT NULL,
last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (country_id)
)
Some MySQL DDL syntax is supported in the MYS syntax mode of HSQLDB, for example AUTO_INCREMENT is translated to IDENTITY, but others need manual editing. The data is mostly compatible, apart from some binary strings.
You need to access the database with a tool that reports the query time. The HSQLDB DatabaseManager does this when the query output is in Text mode.

Resources