How can I set a custom-default value in SQL Server? - sql-server

Im trying to set a default value for a field into a SQL Server Table.
This field is int, and when I go to the GUI and I set Associated Default Value to 0 and I save the table, than the default value will be ((0)) (and when I insert a record it get the NULL value).
Why? How can I fix it?

You are sending NULL.
If you want it to use the default, then don't specify it or use the keyword DEFAULT
INSERT (col1, col3) -- col2 is skipped, gets zero default
VALUE (foo, bar)
INSERT (col1, col2, col3)
VALUE (foo, DEFAULT, bar)
INSERT -- not best practice
VALUE (foo, DEFAULT, bar)

I just created a table as follows and the default value on testid2 works as expected.
USE [db]
GO
/****** Object: Table [dbo].[Table_1] Script Date: 01/31/2012 10:27:51 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Table_1](
[testid] [int] NULL,
[testid2] [int] NOT NULL CONSTRAINT [DF_Table_1_testid2] DEFAULT ((0))
) ON [PRIMARY]
If you right click on your table, Script Table as..., CREATE TO and then check your result against mine.

If it inserts NULL is because you are probably specifying the column name on the query.
If you do:
insert into table (defaultColumn) values (NULL)
it will ignore the default constraint and insert NULL
There are several scenarios. Try posting your query so we can analyze it

Related

sql server - Procedure that checks if row values from INSERT already exist in database

I need to create procedure that doesn't allow insertion of duplicate values and procedure has to check if column "zipcode" is in valid format (5 digits only).
I didn't find a proper solution yet and that's why I'm writing this.
Thanks in advance for any help!
EDIT: I know about unique constraints, but I'm doing assignment for job recruitment and I HAVE TO implement it via procedure.
Btw is there a alternative in MS SQL to keyword new from MySQL? I need that to do what I want I believe...
Hi for check you can use something like this
ALTER TABLE your_table
ADD CONSTRAINT chk_your_table CHECK (zipcode LIKE '[0-9][0-9][0-9][0-9][0-9]')
for duplicate use UNIQUE
The problem with using a stored procedure is that if any user has UPDATE permissions on the table they can bypass your checking and add invalid and duplicate data, you should therefore use table constraints on the table to handle this or a trigger:
CREATE TABLE #Zip
(
[Id] INT PRIMARY KEY Identity,
[ZIPCode] VARCHAR(5) UNIQUE NOT NULL
CONSTRAINT CK_ZIPCode CHECK ( [ZIPCode] LIKE '[0-9][0-9][0-9][0-9][0-9]' ),
Place VARCHAR(20) NOT NULL
)
Now if you run the following inserts:
Insert into #Zip VALUES ('12345', 'MyPlace')
Insert into #Zip VALUES ('12345', 'MyPlace2')
Insert into #Zip VALUES ('A2345', 'MyPlace3')
Insert into #Zip VALUES ('13345', 'MyPlace4')
The first one succeeds,
the second fails with
Violation of UNIQUE KEY constraint
the third fails with:
The INSERT statement conflicted with the CHECK constraint
"CK_ZIPCode".
and the 4th succeeds.
For any more complex checking you should use a TRIGGER.

Update/insert value using trigger where PK autoincrement in SQL Server

I'm working with my first database and already have a problem. I have several tables. Some of them have PK set to autoincrement, others have nvarchar() type.
I have created trigger, which update or insert value into cell. This trigger works when I manually insert value for PF, in my case for nvarchar() values. It is not working for PK, where is set to autoincrement - int. I need help to create trigger which will work for that typs.
Example of trigger:
ALTER TRIGGER [dbo].[Table_Name_trigger_update]
ON [dbo].[Table_Name]
AFTER UPDATE
AS
BEGIN
UPDATE Table_Name
SET
changed_date = getdate()
, changed_user = CURRENT_USER
FROM inserted AS ij
WHERE ij.ID_name = Table_Name.ID_name
RETURN
END
So as I write earlier, this work on nvarchar(), where I manually insert PK. In that case trigger update the getdate() and CURRENT_USER value in table.
You don't need this trigger actually.
Try to replace it with these Default Constraints:
ALTER TABLE Table_Name ADD DEFAULT (getdate()) FOR changed_date
GO
ALTER TABLE Table_Name ADD DEFAULT (CURRENT_USER) FOR changed_user
GO
You can solve this without a trigger as #GriGrim already stated. But i would suggest another solution:
ALTER TABLE Table_Name ADD DEFAULT (getdate()) FOR changed_date
GO
ALTER TABLE Table_Name ADD DEFAULT (SUSER_SNAME()) FOR changed_user
GO
You can compare the results using this:
SELECT CURRENT_USER, SUSER_SNAME()
CURRENT_USER tends to return dbo not the real username.

Is it possible to associate Unique constraint with a Check constraint?

I have a table access whose schema is as below:
create table access (
access_id int primary key identity,
access_name varchar(50) not null,
access_time datetime2 not null default (getdate()),
access_type varchar(20) check (access_type in ('OUTER_PARTY','INNER_PARTY')),
access_message varchar(100) not null,
)
Access types allowed are only OUTER_PARTY and INNER_PARTY.
What I am trying to achieve is that the INNER_PARTY entry should be only once per day per login (user), but the OUTER_PARTY can be recorded any number of times. So I was wondering if its possible to do it directly or if there is an idiom to create this kind of restriction.
I have checked this question: Combining the UNIQUE and CHECK constraints, but was not able to apply it to my situation as it was aiming for a different thing.
A filtered unique index can be added to the table. This index can be based on a computed column which removes the time component from the access_time column.
create table access (
access_id int primary key identity,
access_name varchar(50) not null,
access_time datetime2 not null default (SYSDATETIME()),
access_type varchar(20) check (access_type in ('OUTER_PARTY','INNER_PARTY')),
access_message varchar(100) not null,
access_date as CAST(access_time as date)
)
go
create unique index IX_access_singleinnerperday on access (access_date,access_name) where access_type='INNER_PARTY'
go
Seems to work:
--these inserts are fine
insert into access (access_name,access_type,access_message)
select 'abc','inner_party','hello' union all
select 'def','outer_party','world'
go
--as are these
insert into access (access_name,access_type,access_message)
select 'abc','outer_party','hello' union all
select 'def','outer_party','world'
go
--but this one fails
insert into access (access_name,access_type,access_message)
select 'abc','inner_party','hello' union all
select 'def','inner_party','world'
go
unfortunately you cant add a "if" on a check constraint. I advise using a trigger:
create trigger myTrigger
on access
instead of insert
as
begin
declare #access_name varchar(50)
declare #access_type varchar(20)
declare #access_time datetime2
select #access_name = access_name, #access_type= access_type, #access_time=access_time from inserted
if exists (select 1 from access where access_name=#access_name and access_type=#access_type and access_time=#access_time) begin
--raise excetion
end else begin
--insert
end
end
you will have to format the #access_time to consider only the date part

SQL Server Update Trigger (Not Unique Insert Issue)

I have a super simple table that looks something like this:
CREATE TABLE [dbo].[TestTable](
[SomeColumn] [int] NOT NULL )
I also have a super simple trigger on another table that looks something like this:
ALTER TRIGGER [dbo].[trg_Audit_TableXYZ] ON [dbo].[TableXYZ] AFTER UPDATE
AS
INSERT INTO [dbo].[TestTable] Values (123)
My problem is that when the trigger runs I get the following error:
The row value(s) updated or deleted either do not make the row unique or they alter multiple rows (2 rows).
I don't get it, why would I get this error?
Thank you.
Add SET NOCOUNT ON to the top of the trigger definition. This will suppress the additional rows affected message that emanates from the trigger and confuses SSMS.
i.e.
ALTER TRIGGER [dbo].[trg_Audit_TableXYZ]
ON [dbo].[TableXYZ]
AFTER UPDATE
AS
SET NOCOUNT ON
--Rest of trigger definition follows
INSERT INTO [dbo].[TestTable] Values (123)
I can't recreate. Is this conflicting with some other trigger or a constraint or something, maybe? I don't know.
Update:
As Mikael said, adding a primary key in TableXYZ will work-around the issue. Only happens when you are modifying the table with SSMS. Thanks Mikael. This works:
create database testdb
go
use testdb
CREATE TABLE [dbo].[TestTable](
[SomeColumn] [int] NOT NULL)
CREATE TABLE [dbo].[TableXYZ](
[ID] [int] identity(1,1) primary key,
[SomeColumn] [int] NOT NULL )
go
create TRIGGER [dbo].[trg_Audit_TableXYZ] ON [dbo].[TableXYZ] AFTER UPDATE
AS
INSERT INTO [dbo].[TestTable] Values (123)
go
INSERT INTO [dbo].[Tablexyz] Values (4)
INSERT INTO [dbo].[Tablexyz] Values (5)
INSERT INTO [dbo].[Tablexyz] Values (6)
update tablexyz set somecolumn = 789
update tablexyz set somecolumn = 0

SQL insert default value

SQL Server 2000
Say if I have a table like
CREATE TABLE [Message] (
[MessageIdx] [int] IDENTITY (1, 1) NOT NULL ,
[Message] [varchar] (1024) COLLATE Latin1_General_CI_AS NOT NULL ,
[column1] ... ,
[column2] ... ,
... ,
[ValidUntil] [datetime] NULL ,
CONSTRAINT [PK_Message] PRIMARY KEY CLUSTERED
(
[MessageIdx]
) WITH FILLFACTOR = 90 ON [PRIMARY]
) ON [PRIMARY]
GO
Since there're too many columns, so I am trying to insert value without specify column names explicitly. I want to insert a new row with all columns except 'MessageIdx' and 'ValidUntil' not specified. Therefore, I definitely don't want to type all column names.
I tried below statement but it causes error. How can I do that? Thanks.
insert into message values (DEFAULT,'blah',something, ..., DEFAULT);
EDIT: AFAIN, SQL 2005 server you can skip the identity column when inserting. So that will be
insert into message values ('blah',something, ..., DEFAULT);
But is there any work around for SQL server 2000?
you have to specify column names if you use set identity_insert
but you can do this
set identity_insert caconfig..fxmessage on;
insert into message (MessageIdx,[Message],[ValidUntil)
values (1,'blah',GETDATE());
set identity_insert caconfig..fxmessage off;
I assume what you really want is this, it will generate the identity value for you
insert into message ([Message],[ValidUntil) values ('blah',GETDATE());
Don't be lazy. Do it the correct way, which is to specify the column list (excluding the identity column).
Use getdate(), and for IDENTITY columns (if using uniqueidentifier which I see you're not), you can use newid(), and set them in the design-view of the table in the default value. After that you'd simply go:
INSERT INTO Message (Message) VALUES ('blah');

Resources