I have a problem when i create a table in SQL Server
once i chose DOUBLE as the data type, the error jumped on my face !!!
THIS is the following code :
CREATE TABLE BATCH
( Product_Name VARCHAR(200) NOT NULL,
Product_Brand VARCHAR(100) NOT NULL,
CONSTRAINT Price_FK FOREIGN KEY (Product_Name,Product_Brand)REFERENCES Product (Product_Name,Product_Brand),
BATCH_Date AS GETDATE(),
BATCH_OriginalPrice DOUBLE NOT NULL DEFAULT 0,
BATCH_TAX DOUBLE NOT NULL DEFAULT 0,
BATCH_ProductCost DOUBLE NOT NULL DEFAULT 0 ,
)
The error is like this after each double
Incorrect syntax near the keyword 'NOT'
and when i pass the mouse over it, it says
" Incorrect syntax near 'NOT'. Expecting ID "
Can someone tell me what's the problem !!!
double isn't a data type in SQL, you'll have to use float or real.
With your example you could use money as well.
related: What represents a double in sql server?
You cannot use DOUBLE in SQL SERVER. Try using Decimal or Float or Real or Money or even Smallmoney. See HERE
CREATE TABLE BATCH
( Product_Name VARCHAR(200) NOT NULL,
Product_Brand VARCHAR(100) NOT NULL,
CONSTRAINT Price_FK FOREIGN KEY (Product_Name,Product_Brand)REFERENCES Product (Product_Name,Product_Brand),
BATCH_Date AS GETDATE(),
BATCH_OriginalPrice REAL NOT NULL DEFAULT 0,
BATCH_TAX REAL NOT NULL DEFAULT 0,
BATCH_ProductCost REAL NOT NULL DEFAULT 0 ,
)
Try to use DECIMAL, FLOAT or REAL datatypes -
CREATE TABLE BATCH (
Product_Name VARCHAR(200) NOT NULL,
Product_Brand VARCHAR(100) NOT NULL,
BATCH_OriginalPrice DECIMAL(18,2) NOT NULL DEFAULT 0,
BATCH_TAX DECIMAL(18,2) NOT NULL DEFAULT 0,
BATCH_ProductCost DECIMAL(18,2) NOT NULL DEFAULT 0 ,
BATCH_Date AS GETDATE(),
CONSTRAINT Price_FK FOREIGN KEY (Product_Name,Product_Brand)
REFERENCES Product (Product_Name,Product_Brand)
)
Related
I have a table with 39 column and 30 rows in Sybase.I am trying to Concat all the 39 columns in a single column with 30 rows.
Tools used:
Winsql professional 4.5 connect to Sybase DB
table1 has actual data
Created a temp table2 of data type text. Create table #temp2 (Line text)
Insert and formatted using trim for space,null values and tried concat using + symbol into temp table2 from table1
Result: data gets truncated at 256 char
Findings: Sybase ASE text data type supports only 255 char
Can someone suggest on how to overcome with this issue!
Sybase ASE's text data type is not limited to 256 characters, but there are some tricks to using it successfully such as specifying textsize and being aware that these settings may be session and stored procedure specific.
Consider the following example Sybase ASE 16.0 GA on Linux:
Create then 39 column table.
create table table_1 (
col_1 Varchar(255) null,
col_2 Varchar(255) null,
col_3 Varchar(255) null,
col_4 Varchar(255) null,
col_5 Varchar(255) null,
col_6 Varchar(255) null,
col_7 Varchar(255) null,
col_8 Varchar(255) null,
col_9 Varchar(255) null,
col_10 Varchar(255) null,
col_11 Varchar(255) null,
col_12 Varchar(255) null,
col_13 Varchar(255) null,
col_14 Varchar(255) null,
col_15 Varchar(255) null,
col_16 Varchar(255) null,
col_17 Varchar(255) null,
col_18 Varchar(255) null,
col_19 Varchar(255) null,
col_20 Varchar(255) null,
col_21 Varchar(255) null,
col_22 Varchar(255) null,
col_23 Varchar(255) null,
col_24 Varchar(255) null,
col_25 Varchar(255) null,
col_26 Varchar(255) null,
col_27 Varchar(255) null,
col_28 Varchar(255) null,
col_29 Varchar(255) null,
col_30 Varchar(255) null,
col_31 Varchar(255) null,
col_32 Varchar(255) null,
col_33 Varchar(255) null,
col_34 Varchar(255) null,
col_35 Varchar(255) null,
col_36 Varchar(255) null,
col_37 Varchar(255) null,
col_38 Varchar(255) null,
col_39 Varchar(255) null)
go
I receive a warning about the potential row sizes not fitting on the page. My Sybase ASE instance is configured for 2K pages. 16K page size instances will not receive this warning. Truncation will only occur should the row size become larger than the page size:
Warning: Row size (10028 bytes) could exceed row size limit, which is 1962
bytes.
Insert the rows into table_1. Ideally, with 16K pages and columns with 255 characters, this insert statement could be used:
insert into table_1 values (
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789COL01',
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789COL02',
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789COL03',
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789COL04',
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789COL05',
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789COL06',
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789COL07',
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789COL08',
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789COL09',
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789COL10',
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789COL11',
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789COL12',
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789COL13',
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789COL14',
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789COL15',
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789COL16',
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789COL17',
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789COL18',
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789COL19',
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789COL20',
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789COL21',
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789COL22',
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789COL23',
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789COL24',
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789COL25',
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789COL26',
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789COL27',
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789COL28',
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789COL29',
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789COL30',
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789COL31',
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789COL32',
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789COL33',
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789COL34',
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789COL35',
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789COL36',
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789COL37',
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789COL38',
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789COL39')
go 30
The "go 30" at the end, submits the SQL batch 30 times, inserting 30 rows.
Since my own instance only has 2K pages, I'm limiting myself to 45 characters per column which is 1755 characters.
insert into table_1 values (
'0123456789012345678901234567890123456789COL01',
'0123456789012345678901234567890123456789COL02',
'0123456789012345678901234567890123456789COL03',
'0123456789012345678901234567890123456789COL04',
'0123456789012345678901234567890123456789COL05',
'0123456789012345678901234567890123456789COL06',
'0123456789012345678901234567890123456789COL07',
'0123456789012345678901234567890123456789COL08',
'0123456789012345678901234567890123456789COL09',
'0123456789012345678901234567890123456789COL10',
'0123456789012345678901234567890123456789COL11',
'0123456789012345678901234567890123456789COL12',
'0123456789012345678901234567890123456789COL13',
'0123456789012345678901234567890123456789COL14',
'0123456789012345678901234567890123456789COL15',
'0123456789012345678901234567890123456789COL16',
'0123456789012345678901234567890123456789COL17',
'0123456789012345678901234567890123456789COL18',
'0123456789012345678901234567890123456789COL19',
'0123456789012345678901234567890123456789COL20',
'0123456789012345678901234567890123456789COL21',
'0123456789012345678901234567890123456789COL22',
'0123456789012345678901234567890123456789COL23',
'0123456789012345678901234567890123456789COL24',
'0123456789012345678901234567890123456789COL25',
'0123456789012345678901234567890123456789COL26',
'0123456789012345678901234567890123456789COL27',
'0123456789012345678901234567890123456789COL28',
'0123456789012345678901234567890123456789COL29',
'0123456789012345678901234567890123456789COL30',
'0123456789012345678901234567890123456789COL31',
'0123456789012345678901234567890123456789COL32',
'0123456789012345678901234567890123456789COL33',
'0123456789012345678901234567890123456789COL34',
'0123456789012345678901234567890123456789COL35',
'0123456789012345678901234567890123456789COL36',
'0123456789012345678901234567890123456789COL37',
'0123456789012345678901234567890123456789COL38',
'0123456789012345678901234567890123456789COL39')
go 30
Check the correct number of characters have been entered, this should be the length of string in each column. In my own case, 45.
select
char_length(col_1),
char_length(col_2),
char_length(col_3),
char_length(col_4),
char_length(col_5),
char_length(col_6),
char_length(col_7),
char_length(col_8),
char_length(col_9),
char_length(col_10),
char_length(col_11),
char_length(col_12),
char_length(col_13),
char_length(col_14),
char_length(col_15),
char_length(col_16),
char_length(col_17),
char_length(col_18),
char_length(col_19),
char_length(col_20),
char_length(col_21),
char_length(col_22),
char_length(col_23),
char_length(col_24),
char_length(col_25),
char_length(col_26),
char_length(col_27),
char_length(col_28),
char_length(col_29),
char_length(col_30),
char_length(col_31),
char_length(col_32),
char_length(col_33),
char_length(col_34),
char_length(col_35),
char_length(col_36),
char_length(col_37),
char_length(col_38),
char_length(col_39)
from table_1
go
Now create table_2 with the text column.
create table table_2 (col_1 text null)
go
Insert the rows into table_2 from the concatenated values of the columns in table_1. There will be one row in table_2 for each row in table_1.
insert into table_2 select
col_1 +
col_2 +
col_3 +
col_4 +
col_5 +
col_6 +
col_7 +
col_8 +
col_9 +
col_10 +
col_11 +
col_12 +
col_13 +
col_14 +
col_15 +
col_16 +
col_17 +
col_18 +
col_19 +
col_20 +
col_21 +
col_22 +
col_23 +
col_24 +
col_25 +
col_26 +
col_27 +
col_28 +
col_29 +
col_30 +
col_31 +
col_32 +
col_33 +
col_34 +
col_35 +
col_36 +
col_37 +
col_38 +
col_39 as result
from table_1
go
Check the length of the column in table_2. If using 45 characters it should be 1755; if using 255 characters it should be 9945.
select char_length(col_1) from table_2
go
Confirm the last value of the last row ends in "COL39".
select col_1 from table_2
go
Something like...
0123456789012345678901234567890123456789COL39
Given the above test case was conducted using Sybase's isql utility we can show that Sybase ASE does correctly concatenate the values and store them in a text column. You are using "winsql", a tool that I am not familiar with nor do I have access to. I imagine this may be imposing some limits on what is being displayed. I suspect somewhere it maybe running:
set textsize 255
or simply truncating the data. The above test case should be able to confirm this. The values returned by char_length() will not be subjected to the truncation unless the input data is truncated.
After installing Sybase ASE 12.5.1 on Windows 2000 and configuring it for 16K pages, the commands above were executed in a database called "rwc". The commands worked as advertised.
I am new to sql programming. This is for a homework assignment for my database class. I have made all the table I need for the assignment I am just hung up one part. The line in the homework reads as follows:
If type is 'faculty' the email address must end up with '#xxx.edu'
This is what the table looks like:
create table customer
(
CID# char(10) primary key IDENTITY (1,1) NOT NULL,
F_name varchar(20),
M_name varchar(20),
L_name varchar(20),
type varchar(20),
street varchar(20),
city varchar(20),
state varchar(20),
zip char(5),
password varchar (20) NOT NULL,
email varchar(20) NOT NULL
Constraint CK_customer_type check (type in ('student', 'faculty'))
)
Any help someone could lend would be greatly appreciated!
This constraint would check if the email column ends with #xxx.edu.
Constraint CK_email_faculty check (
type<>'faculty' OR
CHARINDEX('#xxx.edu',email)=LEN(email)-LEN('#xxx.edu')+1
)
Remark 1: Better than checking the type being appropriate in a CHECK constraint, make a table customer_type with possible types ('student', 'faculty' ...), and have a foreign key in customer pointing a the type.
CREATE TABLE customer_type(id INT NOT NULL PRIMARY KEY,desc VARCHAR(128));
INSERT INTO customer_type(id,desc)VALUES(1,'student');
INSERT INTO customer_type(id,desc)VALUES(2,'faculty');
Have a foreign key in your customer table to point to the customer_type table:
CREATE TABLE customer(
-- ...
type INT NOT NULL,
-- ...
CONSTRAINT FK_type_customer_type FOREIGN KEY(type) REFERENCES customer_type(id)
)
You would then not insert the type description but the type identifier:
INSERT INTO customer(...,type,...)VALUES(...,1,...); -- for student
INSERT INTO customer(...,type,...)VALUES(...,3,...); -- fails, type doesn't exist
That way you save disk space, and memory when these tables are cached by SQL Server.
Remark 2: The widths of your varchar fields are very small. An email address of only 20 characters?
For your particular case a constraint like this might be ok:
Constraint CK_customer_email check (
type <> 'faculty' OR
email LIKE '%_%#_%.edu'
CHARINDEX('#xxx.edu',email)=LEN(email)-LEN('#xxx.edu')+1
)
This will allow 1+ characters, followed by #, followed by 1+ characters, followed by .edu.
However, in real life (where mean people try to insert bad e-mail addresses), validation is more complex (not all characters are allowed), so a custom function can be used. One that seems to be almost complete is provided here:
CREATE FUNCTION [dbo].[fnAppEmailCheck](#email VARCHAR(255))
--Returns true if the string is a valid email address.
RETURNS bit
as
BEGIN
DECLARE #valid bit
IF #email IS NOT NULL
SET #email = LOWER(#email)
SET #valid = 0
IF #email like '[a-z,0-9,_,-]%#[a-z,0-9,_,-]%.[a-z][a-z]%'
AND LEN(#email) = LEN(dbo.fnAppStripNonEmail(#email))
AND #email NOT like '%#%#%'
AND CHARINDEX('.#',#email) = 0
AND CHARINDEX('..',#email) = 0
AND CHARINDEX(',',#email) = 0
AND RIGHT(#email,1) between 'a' AND 'z'
SET #valid=1
RETURN #valid
END
Then, your constraint would be like this:
Constraint CK_customer_email check (
type <> 'faculty' OR
[dbo].[fnAppEmailCheck] (email) = 1
)
Add Constraint
Constraint CK_email check (email like case when type in ('faculty') then '%#xxx.edu' else email end )
What am i missing?
create table Diver(
diver_number int primary key check(diver_number>0) not null,
first_name char(30) not null,
last_name char(30) not null,
fullname AS first_name+' '+last_name,
bithdate date not null,
email nchar(100) not null,
diver_password char(8) not null check(Len(diver_password) = 8
AND diver_password not like('%[^a-z0-9]%')),
diver_signature nchar(200) not null,
signature_date date not null,
old_diving_diaries nchar(200))
insert into Diver VALUES('1111','Dana','shwartz','1966/04/11','danas#gmail.com','dana1234','http://www.google.co.il','')
I'm getting this error:
Column name or number of supplied values does not match table definition.
Why?
Yup, the error pretty much speaks for itself. You're trying to insert 8 values into a table with 10 columns.
Consider listing the column names you wish to insert into explicitly
insert into Diver (column names here)
VALUES('1111','Dana','shwartz','1966/04/11','danas#gmail.com','dana1234','http://www.google.co.il','')
You miss old_diving_diaries.
You need to chage the values to
VALUES('1111','Dana','shwartz','1966/04/11','danas#gmail.com','dana1234','http://www.google.co.il','',
'') <-- this
You need only 9 data because of the computed column.
The number of values and data_types must be the same.
VALUES('1111','Dana','shwartz','1966/04/11','danas#gmail.com','dana1234','http://www.google.co.il','ds2016','sdd1','odd1')
10 values needed to pass. Now it must run.
I am trying to store Arabic-strings in my database. it is working fine by using COLLATE Arabic_CI_AI_KS_WS but some of Arabic records are missing some Arabic-alphabets. i have tried with some other sollate with but result as same. how to fix it ?
table structure :
CREATE TABLE [dbo].[Ayyat_Translation_Language_old_20131209] (
[Ayat_Translation_Language_ID] INT IDENTITY (1, 1) NOT NULL,
[Translation_Laanguage_ID] INT NULL,
[Juz_ID] INT NULL,
[Surah_ID] INT NOT NULL,
[Ayat_Description] VARCHAR (2000) COLLATE Arabic_CI_AI_KS_WS NOT NULL
)
insertion code :
string query = "insert into Ayyat_Translation_Language_old_20131209 values(null,null," + surah + ",N'" + verse + "')"; where verse contains Arabic contents.
and it stores data like this (with question-marks) :
?بِسْمِ اللَّهِ الرَّحْمَ?نِ الرَّحِيمِ
i have read that link : store arabic in SQL database
To store unicode string data, use NVARCHAR(2000) rather than VARCHAR(2000) for column [Ayat_Description]
Ref.: nchar and nvarchar
All of what you have to do is to make sure that
the column Data type is nvarchar()
after that I inserted Arabic with no problems even with Tashkeel
this in SQl server management studio 2012
It may help
CREATE TABLE [dbo].[Ayyat_Translation_Language_old_20131209] (
[Ayat_Translation_Language_ID] INT IDENTITY (1, 1) NOT NULL,
[Translation_Laanguage_ID] INT NULL,
[Juz_ID] INT NULL,
[Surah_ID] INT NOT NULL,
[Ayat_Description] NVARCHAR (2000) COLLATE Arabic_CI_AI_KS_WS NOT NULL
use arabic collation or use unicode(nvarchar(max))
This is a Example table For your answer :
CREATE TABLE #t11
(
column1 NVARCHAR(100)
)
INSERT INTO #t11 VALUES(N'لا أتكلم العربية')
SELECT * FROM #t11
fiddle demo
I wish to make sure that my data has a constraint the following check (constraint?) in place
This table can only have one BorderColour per hub/category. (eg. #FFAABB)
But it can have multiple nulls. (all the other rows are nulls, for this field)
Table Schema
ArticleId INT PRIMARY KEY NOT NULL IDENTITY
HubId TINYINT NOT NULL
CategoryId INT NOT NULL
Title NVARCHAR(100) NOT NULL
Content NVARCHAR(MAX) NOT NULL
BorderColour VARCHAR(7) -- Can be nullable.
I'm gussing I would have to make a check constraint? But i'm not sure how, etc.
sample data.
1, 1, 1, 'test', 'blah...', '#FFAACC'
1, 1, 1, 'test2', 'sfsd', NULL
1, 1, 2, 'Test3', 'sdfsd dsf s', NULL
1, 1, 2, 'Test4', 'sfsdsss', '#AABBCC'
now .. if i add the following line, i should get some sql error....
INSERT INTO tblArticle VALUES (1, 2, 'aaa', 'bbb', '#ABABAB')
any ideas?
CHECK constraints are ordinarily applied to a single row, however, you can cheat using a UDF:
CREATE FUNCTION dbo.CheckSingleBorderColorPerHubCategory
(
#HubID tinyint,
#CategoryID int
)
RETURNS BIT
AS BEGIN
RETURN CASE
WHEN EXISTS
(
SELECT HubID, CategoryID, COUNT(*) AS BorderColorCount
FROM Articles
WHERE HubID = #HubID
AND CategoryID = #CategoryID
AND BorderColor IS NOT NULL
GROUP BY HubID, CategoryID
HAVING COUNT(*) > 1
) THEN 1
ELSE 0
END
END
Then create the constraint and reference the UDF:
ALTER TABLE Articles
ADD CONSTRAINT CK_Articles_SingleBorderColorPerHubCategory
CHECK (dbo.CheckSingleBorderColorPerHubCategory(HubID, CategoryID) = 1)
Another option that is available is available if you are running SQL2008. This version of SQL has a feature called filtered indexes.
Using this feature you can create a unique index that includes all rows except those where BorderColour is null.
CREATE TABLE [dbo].[UniqueExceptNulls](
[HubId] [tinyint] NOT NULL,
[CategoryId] [int] NOT NULL,
[BorderColour] [varchar](7) NULL,
)
GO
CREATE UNIQUE NONCLUSTERED INDEX UI_UniqueExceptNulls
ON [UniqueExceptNulls] (HubID,CategoryID)
WHERE BorderColour IS NOT NULL
This approach is cleaner than the approach in my other answer because it doesn't require creating extra computed columns. It also doesn't require you to have a unique column in the table, although you should have that anyway.
Finally, it will also be much faster than the UDF/Check Constraint solutions.
You can also do a trigger with something like this (this is actually overkill - you can make it cleaner by assuming the database is already in a valid state - i.e. UNION instead of UNION all etc):
IF EXISTS (
SELECT COUNT(BorderColour)
FROM (
SELECT INSERTED.HubId, INSERTED.CategoryId, INSERTED.BorderColour
UNION ALL
SELECT HubId, CategoryId, BorderColour
FROM tblArticle
WHERE EXISTS (
SELECT *
FROM INSERTED
WHERE tblArticle.HubId = INSERTED.HubId
AND tblArticle.CategoryId = INSERTED.CategoryId
)
) AS X
GROUP BY HubId, CategoryId
HAVING COUNT(BorderColour) > 1
)
RAISEERROR
If you have a unique column in your table, then you can accomplish this by creating a unique constraint on a computer column.
The following sample created a table that behaved as you described in your requirements and should perform better than a UDF based check constraint. You might also be able to improve the performance further by making the computed column persisted.
CREATE TABLE [dbo].[UQTest](
[Id] INT IDENTITY(1,1) NOT NULL,
[HubId] TINYINT NOT NULL,
[CategoryId] INT NOT NULL,
[BorderColour] varchar(7) NULL,
[BorderColourUNQ] AS (CASE WHEN [BorderColour] IS NULL
THEN cast([ID] as varchar(50))
ELSE cast([HuBID] as varchar(3)) + '_' +
cast([CategoryID] as varchar(20)) END
),
CONSTRAINT [UQTest_Unique]
UNIQUE ([BorderColourUNQ])
)
The one possibly undesirable facet of the above implementation is that it allows a category/hub to have both a Null AND a color defined. If this is a problem, let me know and I'll tweak my answer to address that.
PS: Sorry about my previous (incorrect) answer. I didn't read the question closely enough.