Can you create a table with indexes at the same time? - sql

I'd like to create a table:
CREATE TABLE sfc.OpenId (
Url VARCHAR(255) PRIMARY KEY,
UserGuid uniqueidentifier NOT NULL references dbo.aspnet_users(userId),
)
...with an index on UserGuid.
Is it possible to create that index in the create table statement?

You can do that if the index on UserGuid is a unique index, via UNIQUE constraint. Otherwise, no.

Is it possible to create that index in the create table statement?
No, only constraints can be created within the CREATE TABLE syntax.
f not defined otherwise, the primary key will automatically be a CLUSTERED index - but that doesn't cover the userguid column. The CREATE INDEX syntax needs to be a separate statement otherwise.

Can you clarify why?
You can use transactions with DDL in SQL server and for most purposes this is equivalent to doing it at the same time.

Related

What is the statement to create a primary key in SQL like "3585c5d240dd4132bab35ab969137f3f"

I'm working with SQL Server Management Studio. I want to create a primary key like "3585c5d240dd4132bab35ab969137f3f" with a statement from SQL but I don't know the statement to create a primary key.
Can someone tell me what the statement is, to create a primary key like this?
First, you need to add a column that will store that GUID.
alter table your_table
add field_name uniqueidentifier not null
Then you need to create your primary key constraint on that field.
alter table your_table
add constraint PK_[your_table] PRIMARY KEY(field_name)
Lastly, when inserting data into your table, the field_name is generated using newid() like so:
insert into your_table(field_name)
values(newid())
This value seems to be a Universally Unique IDentifier, or UUID for short.
In MS SQL Server, you can use the newid() function to generate such an identifier. E.g.:
SELECT NEWID()
One way to go is to use a GUID. In SQL Server, the function NEWID (see the doc here). If you don't like dashes, use REPLACE as well:
SELECT REPLACE(NEWID(), "-", "");
But beware of guids as primary key: The Cost of GUIDs as Primary Keys. It is a bit old, but still interesting.
To make it a primary key, you can:
declare a primary key of type varchar() in your create statement
since functions are not allowed as default values, use a trigger before insert that uses the function stated above to generate your primary key.
I agree with everyone that says that you need to use the NEWID() function to generate what you want. My recommendation is that if that column will also be your clustered index, you should probably use NEWSEQUENTIALID(), to avoid the horrible fragmentation and page splits a random GUID column may cause.
Try this code:
ALTER TABLE Persons ADD CONSTRAINT pk_PersonID PRIMARY KEY (P_Id, LastName);

Assigning an index to a constraint

I have a script written for Oracle databases that I'm converting to work in SQL Server and I have two questions about a specific section of code.
In Oracle script I have this code:
CREATE UNIQUE INDEX "PK_PORTALROLES" ON "PORTAL_ROLE" ("ROLE_NAME");
ALTER TABLE "PORTAL_ROLE" ADD CONSTRAINT "PK_PORTALROLES"
PRIMARY KEY ("ROLE_NAME") USING INDEX ENABLE;
Question (1)
From the code above what is the USING INDEX command in the ALTER TABLE line doing? Is it assigning the UNIQUE INDEX created on the first line to the newly created CONSTRAINT or is the CONSTRAINT getting a new UNIQUE INDEX to use when it is created?
Question (2)
To duplicate this in SQL Server, I commented out the CREATE UNIQUE INDEX line like this:
--CREATE UNIQUE INDEX "PK_PORTALROLES" ON "PORTAL_ROLE" ("ROLE_NAME");
And then replaced the ALTER TABLE line with this:
ALTER TABLE "PORTAL_ROLE" ADD CONSTRAINT "PK_PORTALROLES" PRIMARY KEY ("ROLE_NAME");
I understand that when a PRIMARY KEY CONSTRAINT is created in SQL Server a UNIQUE INDEX is automatically made. So is the one line of SQL Server code directly above doing the same thing as the two lines of Oracle code above?
EDIT
One final question. Is there a way in Oracle and SQL Server to assign an existing INDEX to a CONSTRAINT?
In Oracle
If there are more than one indexes on the column on which you want to add PK constraint, we can selectively choose the index to be assoicated with the PK using “USING INDEX“. This clause can be used while:
Adding the PK constraint for the first time (using “ALTER TABLE” command).
CREATE TABLE tbl_test ( col_1 NUMBER,
col_2 NUMBER,
col_3 NUMBER);
CREATE INDEX idx_col_1_2 ON tbl_test(col_1, col_2);
CREATE INDEX idx_col_1_3 ON tbl_test(col_1, col_3);
CREATE UNIQUE INDEX idx_col_1 ON tbl_test(col_1);
-- Forcing oracle to use the unique index "IDX_COL_1"
ALTER TABLE tbl_test ADD CONSTRAINT tbl_test_pk PRIMARY KEY(col_1)
USING INDEX idx_col_1;
SELECT constraint_name, constraint_type, index_name
FROM user_constraints
WHERE table_name = 'TBL_TEST';
-- CONSTRAINT_NAME | CONSTRAINT_TYPE | INDEX_NAME
-- TBL_TEST_PK | P | IDX_COL_1
What if? If you don't use the USING INDEX clause
ALTER TABLE tbl_test ADD CONSTRAINT tbl_test_pk PRIMARY KEY(col_1);
-- Although an unique index exists, oracle has picked up the first index
SELECT constraint_name, constraint_type, index_name
FROM user_constraints
WHERE table_name = 'TBL_TEST';
-- CONSTRAINT_NAME | CONSTRAINT_TYPE | INDEX_NAME
-- TBL_TEST_PK | P | IDX_COL_1_2
That shows The index associated with the PK constraint needn’t be unique.
But in SQLServer implicitly CLUSTERED INDEX will be created when primary key defined on any column
So to your last question. In Oracle you can assign index which we created can be assigned to constraints which we will create in future.
In SQLServer i guess it is not possible.
In Oracle, you can do
alter table PORTAL_ROLE add constraint pk_portalroles primary key('ROLE_NAME');
And it will create unique index for you. But when you drop or disable(!) constraint, it will drop that index. To avoid that (or to give index some custom name, or to use non-unique index, etc), it is usually done in 2 steps as in your code (as recommended by ORACLE).
Q1: constraint will be using existing index.
Q2: Yes, it will be enough for SQL Server.
When you specify a unique constraint on one or more columns, Oracle implicitly creates an index on the unique key. If you are defining uniqueness for purposes of query performance, then Oracle recommends that you instead create the unique index explicitly using a CREATE UNIQUE INDEX statement. You can also use the CREATE UNIQUE INDEX statement to create a unique function-based index that defines a conditional unique constraint.

Adding in a primary key to an SQL view

I have created a view in a SQL Server database which is just a join of two tables.
Is there any way I can insert a unique primary key into the rows of this view ...or I'm not sure how I can specify one of the column names to be a primary key...any ideas?
Thanks
You would have to create materialized (indexed) view in order to be able to add unique index. But you can't create PK constraint.
CREATE VIEW v_test
WITH SCHEMABINDING --optional
AS
SELECT id from table
GO
CREATE UNIQUE CLUSTERED INDEX idx_id
ON v_test (id)
GO

H2 database: Information about primary key in INFORMATION_SCHEMA

I create the following table in H2:
CREATE TABLE TEST
(ID BIGINT NOT NULL PRIMARY KEY)
Then I look into INFORMATION_SCHEMA.TABLES table:
SELECT SQL
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = 'TEST'
Result:
CREATE CACHED TABLE TEST(
ID BIGINT NOT NULL
)
Then I look into INFORMATION_SCHEMA.CONSTRAINTS table:
SELECT SQL
FROM INFORMATION_SCHEMA.CONSTRAINTS
WHERE TABLE_NAME = 'TEST'
Result:
ALTER TABLE TEST
ADD CONSTRAINT CONSTRAINT_4C
PRIMARY KEY(ID)
INDEX PRIMARY_KEY_4C
These statements are not the ones which I have stated, therefore, the question is:
Is the information in TABLES and CONSTRAINS reflects how real SQL which was executed in database?
In original CREATE TABLE statement
there was no CACHED word. (not a problem)
I have never executed ALTER TABLE .. ADD CONSTRAINT statement.
The actual reason why I am asking the question is that I am not sure which statement should I execute in order to guarantee that primary key is used in a clustered index.
If you look at my previous question H2 database: clustered index support then you may find in the answer of Thomas Mueller the following statement:
If a primary key is created after the table has been created then the primary key is stored in a new index b-tree.
Therefore, if the statements are executed as such they are shown in INFORMATION_SCHEMA, then primary key is created after the table is created and hence ID is not used in a clustered index (basically as a key in a data b-tree).
Is there a way how one can guarantee that primary key is used in a clustered index in H2?
Is the information in TABLES and CONSTRAINS reflects how real SQL which was executed in database?
Yes. Basically, those are the statements that are run when opening the database.
If you look at my previous question
The answer "If a primary key is created after the table has been created..." was incorrect, I fixed it now to "If a primary key is created after data has been inserted...".
Is there a way how one can guarantee that primary key is used as a clustered index in H2?
This is now better described in the H2 documentation at "How Data is Stored Internally": "If a single column primary key of type BIGINT, INT, SMALLINT, TINYINT is specified when creating the table (or just after creating the table, but before inserting any rows), then this column is used as the key of the data b-tree."

What to use for SQL Server instead of "Key"?

I have a script of MySQL queries that I use and that work.
I'm trying to execute the same queries in Microsoft SQL server and there's one thing I don't understand.
MySql uses "key" to define a key made up of different fields.
What is the way to do the same thing in SQL Server?
Thanks!
-Adeena
You can declare a primary key that consists of multiple columns in TSQL (SQL server's query language)
ALTER TABLE product
ADD CONSTRAINT prim_prod PRIMARY KEY(product_foo, product_bar)
If you use SQL Server Management studio, you can also achieve this via "Modify Table".
In MySQL, the keyword KEY is simply a synonym for INDEX. The following two are equivalent:
CREATE TABLE foo (
id SERIAL PRIMARY KEY,
ctime DATETIME,
KEY ctkey (ctime)
);
CREATE TABLE foo (
id SERIAL PRIMARY KEY,
ctime DATETIME,
INDEX ctidx (ctime)
);
In Microsoft SQL Server, the closest equivalent is INDEX. As far as I can tell, to create an index on a column in Microsoft SQL Server, you use CREATE INDEX. You can also create constraints that build indexes as part of a CREATE TABLE statement, but if you just need an index, use CREATE INDEX.
CREATE TABLE foo (
id BIGINT IDENTITY PRIMARY KEY,
ctime DATETIME
);
CREATE INDEX ctidx ON foo(ctime);
See also documentation on CREATE INDEX.