I have this table:
CREATE TABLE [dbo].[SandTable](
[Id] [uniqueidentifier] NOT NULL,
[Date] [date] NULL,
CONSTRAINT [PK_SandTable] PRIMARY KEY)
ALTER TABLE [dbo].[SandTable] ADD CONSTRAINT [DF_SandTable_Id] DEFAULT (NEWID()) FOR [Id]
Question is not about using NEWID() vs NEWSEQUENTIALID().
I use linqPad to test the table.
SandTables.InsertOnSubmit(new SandTable
{
// I don't provide any value for Id
Date = DateTime.Now
});
SubmitChanges();
My initial idea was to create an Id column that is able to initialize itself to a value when no Id is provided but will use the id provided when one is provided.
But because Guid is a struct, not a class the Id is never null, Id is initialized to his default value (00000000-0000-0000-0000-000000000000). So SQL server consider that Id has always a value and then the NEWID() default instruction is never called.
Is it possible to force the call to NEWID() on specific value? Should I use a trigger to evaluate the value of Id and when it's (00000000-0000-0000-0000-000000000000) then call NEWID()? What are the solutions or workaround?
You can do it with a check constraint:
ALTER TABLE [dbo].[SandTable]
ADD CONSTRAINT [DF_SandTable_Id] DEFAULT (NEWID()) FOR [Id]
ALTER TABLE [dbo].[SandTable]
WITH CHECK ADD CONSTRAINT [CK_SandTable_Id_Empty]
CHECK (
[Id] <> CAST(0x0 AS UNIQUEIDENTIFIER)
)
Related
I'm creating the following table:
CREATE TABLE [dbo].[Symptoms]
(
[Id] INT NOT NULL,
[description] NVARCHAR (128) NOT NULL,
[imgPath] NVARCHAR (128) NOT NULL,
[diseaseId] INT NOT NULL,
[weight] FLOAT NOT NULL,
PRIMARY KEY CLUSTERED ([Id] ASC, [diseaseId] ASC)
);
What I want to do is create a default value for the [imgPath] column. I know about DEFAULT newid() and other methods, but I want a custom generated method.
Specifically, I want the [imgPath] to be $"/resources/Images/{Id}_symptom.jpg" where Id is the ID of that specific row.
Where can I specify this function?
Thanks!
Update
Column defaults in SQL Server can't be made up using other columns data.
What you can do is add another column for you to specify the image path, and use it as a part of the computed column's declaration:
CREATE TABLE [dbo].[Symptoms] (
[Id] INT NOT NULL,
[description] NVARCHAR (128) NOT NULL,
[UserDefinedImgPath] NVARCHAR (128) NULL,
[imgPath] AS COALESCE(UserDefinedimgPath, '/resources/Images/' + CAST(Id AS NVARCHAR(13)) +'_symptom.jpg') PERSISTED,
[diseaseId] INT NOT NULL,
[weight] FLOAT NOT NULL,
PRIMARY KEY CLUSTERED ([Id] ASC, [diseaseId] ASC)
);
Now, when you want to specify the image page on insert or update, use the UserDefinedImgPath column. When you want the default value, simply leave it null.
When selecting the image path, always use the computed column.
First answer
Use a computed column for imgPath:
CREATE TABLE [dbo].[Symptoms] (
[Id] INT NOT NULL,
[description] NVARCHAR (128) NOT NULL,
[imgPath] AS '/resources/Images/' + CAST(Id AS NVARCHAR(13)) +'_symptom.jpg' PERSISTED,
[diseaseId] INT NOT NULL,
[weight] FLOAT NOT NULL,
PRIMARY KEY CLUSTERED ([Id] ASC, [diseaseId] ASC)
);
Note that you can't update a computed column, nor can you insert a specific value to it.
To add default value please create default constraint, in SQL Server the example is below:
ALTER TABLE Symptoms
ADD CONSTRAINT Symptoms_imgPath
DEFAULT (('/resources/Images/{Id}_symptom.jpg')) FOR imgPath
Other way is to insert default value at the time of insert, like this:
INSERT INTO Symptoms
SELECT '/resources/Images/{Id}_symptom.jpg'
FROM symptoms
WHERE id = NEWID()
I have tried the following solution to try to do the insert/update data table into sql server, but some problems happended. http://www.aspsnippets.com/Articles/SqlBulkCopy--Bulk-Insert-records-and-Update-existing-rows-if-record-exists-using-C-and-VBNet.aspx
I created a table: People
CREATE TABLE [dbo].[People](
[ID] [varchar](10) NOT NULL,
[Name] [varchar](50) NULL,
[Email] [varchar](50) NULL,
[Country] [varchar](50) NULL
) ON [PRIMARY]
Create a user-defined table type : PeopleType
CREATE TYPE [dbo].[PeopleType] AS TABLE(
[ID] [varchar](10) NOT NULL,
[Name][varchar](50) NULL,
[Email][varchar](50) NULL
)
I try to use this table type to create a procedure:Update_People
CREATE PROCEDURE [dbo].[Update_People]
#tblpeople PeopleType READONLY
AS
BEGIN
SET NOCOUNT ON;
MERGE INTO People p1
USING #tblpeople p2
ON p1.ID=p2.ID
WHEN MATCHED THEN
UPDATE SET p1.Name = p2.Name
,p1.Email = p2.Email
WHEN NOT MATCHED THEN
INSERT VALUES(p2.ID, p2.Name, p2.Email);
END
but when I try to use the user-defined table type to create the procedure, An SQL server Error happened.
"Column name or number of supplied values does not match table definition."
Did I do anything wrong or miss something?
Change your Insert statement to this if you don't want to add Countries:
INSERT INTO People(Id, Email, Name) VALUES(p2.ID, p2.Name, p2.Email);
The reason you receive the error is because you don't specify which columns to use the Insert statement expects 4 as 4 are defined in the table. But ou only provide 3.
The other option is to add the Country Property to your user defined type and add the country with the procedure:
CREATE TYPE [dbo].[PeopleType] AS TABLE(
[ID] [varchar](10) NOT NULL,
[Name][varchar](50) NULL,
[Email][varchar](50) NULL,
[Country][varchar](50) NULL
)
INSERT VALUES(p2.ID, p2.Name, p2.Email, p2.Country);
EDIT: I am not sure about the syntax, since I haven't used this in a while, but it could be that you only need to provide the column names like this:
INSERT (Id, Email, Name) VALUES(p2.ID, p2.Name, p2.Email);
I have an empty table that has two column : Id and Title .
The Id is guid type , Primary key , so Not Nullable .
I try to add a constraint for default value of Id , constraint is like this :
ALTER TABLE [dbo].[TestTable] ADD CONSTRAINT [DF_TestTable_Id] DEFAULT (newsequentialid()) FOR [Id]
GO
In Entity Framework , Because Id is not nullable , It fill the Id with '00000000-0000-0000-000000000000' value .
Therefor my constraint in sql doesn't work property for creating new sequentialId() and my first record in table get '00000000-0000-0000-000000000000' value.
And it's so obvious for the second row it get the:
"Vaiolation of PRIMARY KEY Constraint "PK_TestTable". Cannot insert Duplicate Key" error .
I know I could generate guid in .NeT like Guid.NewGuid() and fill the Id with value , But I'm trying to delegate this responsibility to sql and newsequentialId() default value .
I'm wonder how could I do that ?
For full info i put the entire script here :
CREATE TABLE [dbo].[TestTable](
[Id] [uniqueidentifier] NOT NULL,
[Title] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_TestTable] PRIMARY KEY CLUSTERED
(
[Id] 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 [dbo].[TestTable] ADD CONSTRAINT [DF_TestTable_Id] DEFAULT (newsequentialid()) FOR [Id]
GO
Update: My EF database first approach Mapping is:
public partial class TestTable
{
[DatabaseGenerated(DatabaseGenereatedOption.Computed)]
public System.Guid Id {get ;set;}
public string Title {get; set;}
}
Map your property Id as Computed like this:
Property(o => o.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
OR
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; }
OR, if you have edmx you must edit property in designer:
Unless you have some requirement to do this the hard way:
ALTER TABLE [dbo].[TestTable] ADD CONSTRAINT [DF_TestTable_Id]
DEFAULT (NEWID()) FOR [Id]
NEWID() is the TSQL equivalent of GUID.NewGuid()
For example, I have the following Table:
CustomerInfo
cus_id: auto increment, int, is Identity
cus_name: nvarchar
If I use the follow codes to insert the record "Peter",
string name = "Peter";
DataContext DC = new DataContext();
CustomerInfo newCustomer = new CustomerInfo();
newCustomer.cus_name = name;
DC.CustomerInfos.InsertOnSubmit(newCustomer);
DC.SubmitChanges();
The following error returns,
Can't perform Create, Update, or Delete operations on 'Table(CustomerInfo)' because it has no primary key.
Do I need to self-define the cus_id or any other solutions? Thanks!
First of all LINQ-To-SQL needs primary keys in order to be able to do Inserts and Updates, so you probably have to add the Primary Key in your table.
Now, because it is an auto incremented identity column, in your dbml, you have to select the column "cus_id" of the "CustomerInfo" table and go to the properties and set the following:
Auto Generated Value : True
Auto-Sync : OnInsert
This will ensure that when you insert a new row it will get a new id.
naratting from answer 1 of question you'll have to make cus_id as primary key too.
you can also try to do following
CREATE TABLE Customers
(
cus_id int NOT NULL AUTO_INCREMENT,
cus_name varchar(255) NOT NULL,
PRIMARY KEY (cus_id)
)
I got this error to. As far as I manged to fix it was to add a primary key.
This code made me a primary key and made it autoincrement. Maybe it's what you are looking for?
(When you create the table)
columnname bigint IDENTITY(1,1) NOT NULL,
CONSTRAINT pkcolumnname PRIMARY KEY CLUSTERED
I am sure m missing something really small but i am having issue of Primary value auto incremental. I have creates two simple table and I have adopt Existing database model first approach by using Entity Framework 5. I simple adding values in table from console program.
My issue is code works fine for first time, but crashes if i try to add more value by running whole app again and i found the reason; the EF doesn't increment primary index automatically.
table
CREATE TABLE [dbo].[Book_Titles] (
[Book_ID] INT NOT NULL,
[Title] NVARCHAR (150) NOT NULL,
PRIMARY KEY CLUSTERED ([Book_ID] ASC)
);
CREATE TABLE [dbo].[Books_Authors] (
[Author_Id] INT NOT NULL,
[Author_Name] NVARCHAR (150) NOT NULL,
[Book_ID] INT NULL,
PRIMARY KEY CLUSTERED ([Author_Id] ASC),
FOREIGN KEY ([Book_ID]) REFERENCES [dbo].[Book_Titles] ([Book_ID])
);
Console program
namespace Database_First_01
{
class Program
{
static void Main(string[] args)
{
using (var db = new BooksContext())
{
var book = new Book_Titles()
{
Title ="EF ",
};
var author = new Books_Authors()
{
Author_Name = "me!",
};
book.Books_Authors.Add(author);
db.Book_Titles.Add(book);
db.SaveChanges();
}
}
}
}
many thanks in advance.
Try this
CREATE TABLE [dbo].[Book_Titles] (
[Book_ID] INT IDENTITY(1,1) NOT NULL,
[Title] NVARCHAR (150) NOT NULL,
PRIMARY KEY CLUSTERED ([Book_ID] ASC)
);
Define Identity on Column
Same as other if you want.
Microsoft SQL Server uses the IDENTITY keyword to perform an auto-increment feature. and its missing in your case.
You can use IDENTITY property in different cases
Its used with the CREATE TABLE
and ALTER TABLE Transact-SQL statements.
so if you have already created the table ( and it has data ) you may just alter like as follow.
ALTER TABLE (yourTable) ADD NewColumn INT IDENTITY(1,1)
ALTER TABLE (yourTable) DROP COLUMN OldColumnName
sp_rename 'yourTable.NewColumn', 'OldColumnName', 'COLUMN'
and it will save your data in the existing table.
Hope it will help