Constrain Sum(Column) to 1 by some group IDAdd a column with a default value to an existing table in SQL ServerHow to check if a column exists in a SQL Server table?Altering a column: null to not nullHow to 'insert if not exists' in MySQL?Using group by on multiple columnsSelect first row in each GROUP BY group?Find all tables containing column with specified name - MS SQL ServerHow to truncate a foreign key constrained table?SQL select only rows with max value on a columnRename column SQL Server 2008
Why do so many pure math PhD students drop out or leave academia, compared to applied mathematics PhDs?
Cine footage fron Saturn V launch's
Can I remove the doors before installing a sliding patio doors frame?
What powers the air required for pneumatic brakes in aircraft?
What happens if there is no space for entry stamp in the passport for US visa?
Is there a source that says only 1/5th of the Jews will make it past the messiah?
how many bits in the resultant hash will change, if the x bits are changed in its the original input
Should I be able to keep my company purchased standing desk when I leave my job?
Adjusting vertical spacing in fractions?
What exactly is a Hadouken?
Why does "git status" show I'm on the master branch and "git branch" does not?
Did Voldemort kill his father before finding out about Horcruxes?
Why isn't aluminium involved in biological processes?
How can I leave a car for someone if we can't meet in person?
How Can I Process Untrusted Data Sources Securely?
Can a pizza stone be fixed after soap has been used to clean it?
Link of a singularity
What is the meaning of [[:space:]] in bash?
What advantages do focused Arrows of Slaying have over more generic ones?
Get back to US from Canada without passport
Intel 8080-based home computers
(Piano) is the purpose of sheet music to be played along to? Or a guide for learning and reference during playing?
Does the Intel 8085 CPU use real memory addresses?
Is the Gritty Realism variant incompatible with dungeon-based adventures?
Constrain Sum(Column) to 1 by some group ID
Add a column with a default value to an existing table in SQL ServerHow to check if a column exists in a SQL Server table?Altering a column: null to not nullHow to 'insert if not exists' in MySQL?Using group by on multiple columnsSelect first row in each GROUP BY group?Find all tables containing column with specified name - MS SQL ServerHow to truncate a foreign key constrained table?SQL select only rows with max value on a columnRename column SQL Server 2008
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;
I have a table that I'm trying to make sure that an aggregate sum of the inserts adds up to 1 (it's a mixture).
I want to constrain it so the whole FKID =2 fails because it adds up to 1.1.
Currently my constraint is
FUNCTION[dbo].[CheckSumTarget](@ID bigint)
RETURNS bit
AS BEGIN
DECLARE @Res BIT
SELECT @Res = Count(1)
FROM dbo.Test AS t
WHERE t.FKID = @ID
GROUP BY t.FKID
HAVING Sum([t.Value])<>1
RETURN @Res
END
GO
ALTER TABLE dbo.Test WITH CHECK ADD CONSTRAINT [CK_Target_Sum] CHECK (([dbo].[CheckSumTarget]([FKID])<>(1)))
but it's failing on the first insert because it doesn't add up to 1 yet. I was hoping if I add them all simultaneously, that wouldn't be the case.
sql sql-server constraints
add a comment |
I have a table that I'm trying to make sure that an aggregate sum of the inserts adds up to 1 (it's a mixture).
I want to constrain it so the whole FKID =2 fails because it adds up to 1.1.
Currently my constraint is
FUNCTION[dbo].[CheckSumTarget](@ID bigint)
RETURNS bit
AS BEGIN
DECLARE @Res BIT
SELECT @Res = Count(1)
FROM dbo.Test AS t
WHERE t.FKID = @ID
GROUP BY t.FKID
HAVING Sum([t.Value])<>1
RETURN @Res
END
GO
ALTER TABLE dbo.Test WITH CHECK ADD CONSTRAINT [CK_Target_Sum] CHECK (([dbo].[CheckSumTarget]([FKID])<>(1)))
but it's failing on the first insert because it doesn't add up to 1 yet. I was hoping if I add them all simultaneously, that wouldn't be the case.
sql sql-server constraints
add a comment |
I have a table that I'm trying to make sure that an aggregate sum of the inserts adds up to 1 (it's a mixture).
I want to constrain it so the whole FKID =2 fails because it adds up to 1.1.
Currently my constraint is
FUNCTION[dbo].[CheckSumTarget](@ID bigint)
RETURNS bit
AS BEGIN
DECLARE @Res BIT
SELECT @Res = Count(1)
FROM dbo.Test AS t
WHERE t.FKID = @ID
GROUP BY t.FKID
HAVING Sum([t.Value])<>1
RETURN @Res
END
GO
ALTER TABLE dbo.Test WITH CHECK ADD CONSTRAINT [CK_Target_Sum] CHECK (([dbo].[CheckSumTarget]([FKID])<>(1)))
but it's failing on the first insert because it doesn't add up to 1 yet. I was hoping if I add them all simultaneously, that wouldn't be the case.
sql sql-server constraints
I have a table that I'm trying to make sure that an aggregate sum of the inserts adds up to 1 (it's a mixture).
I want to constrain it so the whole FKID =2 fails because it adds up to 1.1.
Currently my constraint is
FUNCTION[dbo].[CheckSumTarget](@ID bigint)
RETURNS bit
AS BEGIN
DECLARE @Res BIT
SELECT @Res = Count(1)
FROM dbo.Test AS t
WHERE t.FKID = @ID
GROUP BY t.FKID
HAVING Sum([t.Value])<>1
RETURN @Res
END
GO
ALTER TABLE dbo.Test WITH CHECK ADD CONSTRAINT [CK_Target_Sum] CHECK (([dbo].[CheckSumTarget]([FKID])<>(1)))
but it's failing on the first insert because it doesn't add up to 1 yet. I was hoping if I add them all simultaneously, that wouldn't be the case.
sql sql-server constraints
sql sql-server constraints
asked Mar 25 at 20:18
FallerFaller
6092 gold badges8 silver badges22 bronze badges
6092 gold badges8 silver badges22 bronze badges
add a comment |
add a comment |
3 Answers
3
active
oldest
votes
This approach seems fraught with problems.
I would suggest another approach, starting with two tables:
aggregates
, so "fkid" should really beaggregate_id
components
Then, in aggregates
accumulate the sum()
of the component values using a trigger. Maintain another flag that is computed:
alter table aggregates add is_valid as ( sum_value = 1.0 )
Then, create views on the two tables to only show records where is_valid = 1
. For instance:
create view v_aggregates as
select c.*
from aggregates a join
components c
on a.aggregate_id = c.aggregate_id
where a.is_value = 1;
But if a user puts in some values that are not valid, wouldn't it just look like they just lost their values?
– Faller
Mar 25 at 20:41
@Faller . . . Are you trying to prevent users from changing values that add up to 1?
– Gordon Linoff
Mar 25 at 21:04
Users enter components of a mixture in percentages. I'm making sure those components add up to 1 (100%).
– Faller
Mar 25 at 21:59
@Faller, in database the best approach you can get is a mix or this computed column and the constraint to prevent sums greater than 1, the rest needs to be done in business layer...
– Daniel Brughera
Mar 26 at 7:48
add a comment |
Here is a working version of solution
Here is table DDL
create table dbo.test(
id int,
fkid bigint,
value decimal(4,2)
);
The function definition
CREATE FUNCTION[dbo].[CheckSumTarget](@ID bigint)
RETURNS bit
AS BEGIN
DECLARE @Res decimal(4,2)
SELECT @Res = case when sum(value) > 1 then 1 else 0 end
FROM dbo.Test AS t
WHERE t.FKID = @ID
RETURN @Res
END
And the constraint defintion
ALTER TABLE dbo.Test WITH CHECK ADD CONSTRAINT [CK_Target_Sum] CHECK ([dbo].[CheckSumTarget]([FKID]) <> 1)
In your example
insert into dbo.test values (1, 2, 0.5);
insert into dbo.test values (1, 2, 0.4);
-- The following insert will fail, like you expect
insert into dbo.test values (1, 2, 0.2);
Note: This solution will be broken by UPDATE statement (as pointed out by 'Daniel Brughera') however that is a known behaviour. A better and common approach is use of trigger. You may want to explore that.
This constraint can be broken with an update
– Daniel Brughera
Mar 25 at 21:52
Yes the update will break this. The better solution is use of a trigger
– Gro
Mar 25 at 22:07
The check can work if you add the value column to the constraint, it’s failing because the fkid wasn’t updated, so, the constraint is not checked again, my approach works for that, but I agree that is not the best solution
– Daniel Brughera
Mar 25 at 22:29
Check my function and the update doesn’t break it
– Daniel Brughera
Mar 25 at 22:30
But this only works for greater than. I need it to add to 1 exactly.
– Faller
Mar 25 at 22:44
|
show 2 more comments
Your actual approach will work this way.....
- You insert the firts component, the value must be 1
- You try to insert a second component, it will be rejected because your sum is already 1
- You update the existing component to .85
- You insert the next component, the value must be .15
- You back to step 2. with the third component
Since your constraint only takes care of the FKID column, it will be possible, and you may think that is working....
But.... if you left the process in step 3. your sum is not equal to 1 and is impossible for the constraint to foresee if you will insert the next value or not, even worst, you can update any value to be greater than 1 and it will be accepted.
If you add the value column to your constraint, it will prevent those updates, but you will never be able to go beyond step 1.
Personally I would't do that, but here you can get an approach
- Use the computed column suggested by Gordon on your parent table. With computed columns you will always get the actual value, so, the parent wont be valid until the sum is equal to one
- Use this solution to prevent the value to be greater than 1, so, at least you will be sure that any non valid parent is because a component is missing, that can be helpful for your business layer
- As I mentioned in one comment, the rest of the logic belongs to the business and ui layers
Note as you can see the id and value parameters are not used in the function, but I need them to call them when I create the constraint, that way the constraint will validate updates too
CREATE TABLE ttest (id int, fkid int, value float)
go
create FUNCTION [dbo].[CheckSumTarget](@id int, @fkid int, @value float)
RETURNS FLOAT
AS BEGIN
DECLARE @Res float
SELECT @Res = sum(value)
FROM dbo.ttest AS t
WHERE t.FKID = @fkid
RETURN @Res
END
GO
ALTER TABLE dbo.ttest WITH CHECK ADD CONSTRAINT [CK_Target_Sum] CHECK (([dbo].[CheckSumTarget](id,[FKID],value)<=(1.0)))
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55345784%2fconstrain-sumcolumn-to-1-by-some-group-id%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
This approach seems fraught with problems.
I would suggest another approach, starting with two tables:
aggregates
, so "fkid" should really beaggregate_id
components
Then, in aggregates
accumulate the sum()
of the component values using a trigger. Maintain another flag that is computed:
alter table aggregates add is_valid as ( sum_value = 1.0 )
Then, create views on the two tables to only show records where is_valid = 1
. For instance:
create view v_aggregates as
select c.*
from aggregates a join
components c
on a.aggregate_id = c.aggregate_id
where a.is_value = 1;
But if a user puts in some values that are not valid, wouldn't it just look like they just lost their values?
– Faller
Mar 25 at 20:41
@Faller . . . Are you trying to prevent users from changing values that add up to 1?
– Gordon Linoff
Mar 25 at 21:04
Users enter components of a mixture in percentages. I'm making sure those components add up to 1 (100%).
– Faller
Mar 25 at 21:59
@Faller, in database the best approach you can get is a mix or this computed column and the constraint to prevent sums greater than 1, the rest needs to be done in business layer...
– Daniel Brughera
Mar 26 at 7:48
add a comment |
This approach seems fraught with problems.
I would suggest another approach, starting with two tables:
aggregates
, so "fkid" should really beaggregate_id
components
Then, in aggregates
accumulate the sum()
of the component values using a trigger. Maintain another flag that is computed:
alter table aggregates add is_valid as ( sum_value = 1.0 )
Then, create views on the two tables to only show records where is_valid = 1
. For instance:
create view v_aggregates as
select c.*
from aggregates a join
components c
on a.aggregate_id = c.aggregate_id
where a.is_value = 1;
But if a user puts in some values that are not valid, wouldn't it just look like they just lost their values?
– Faller
Mar 25 at 20:41
@Faller . . . Are you trying to prevent users from changing values that add up to 1?
– Gordon Linoff
Mar 25 at 21:04
Users enter components of a mixture in percentages. I'm making sure those components add up to 1 (100%).
– Faller
Mar 25 at 21:59
@Faller, in database the best approach you can get is a mix or this computed column and the constraint to prevent sums greater than 1, the rest needs to be done in business layer...
– Daniel Brughera
Mar 26 at 7:48
add a comment |
This approach seems fraught with problems.
I would suggest another approach, starting with two tables:
aggregates
, so "fkid" should really beaggregate_id
components
Then, in aggregates
accumulate the sum()
of the component values using a trigger. Maintain another flag that is computed:
alter table aggregates add is_valid as ( sum_value = 1.0 )
Then, create views on the two tables to only show records where is_valid = 1
. For instance:
create view v_aggregates as
select c.*
from aggregates a join
components c
on a.aggregate_id = c.aggregate_id
where a.is_value = 1;
This approach seems fraught with problems.
I would suggest another approach, starting with two tables:
aggregates
, so "fkid" should really beaggregate_id
components
Then, in aggregates
accumulate the sum()
of the component values using a trigger. Maintain another flag that is computed:
alter table aggregates add is_valid as ( sum_value = 1.0 )
Then, create views on the two tables to only show records where is_valid = 1
. For instance:
create view v_aggregates as
select c.*
from aggregates a join
components c
on a.aggregate_id = c.aggregate_id
where a.is_value = 1;
answered Mar 25 at 20:25
Gordon LinoffGordon Linoff
834k38 gold badges341 silver badges448 bronze badges
834k38 gold badges341 silver badges448 bronze badges
But if a user puts in some values that are not valid, wouldn't it just look like they just lost their values?
– Faller
Mar 25 at 20:41
@Faller . . . Are you trying to prevent users from changing values that add up to 1?
– Gordon Linoff
Mar 25 at 21:04
Users enter components of a mixture in percentages. I'm making sure those components add up to 1 (100%).
– Faller
Mar 25 at 21:59
@Faller, in database the best approach you can get is a mix or this computed column and the constraint to prevent sums greater than 1, the rest needs to be done in business layer...
– Daniel Brughera
Mar 26 at 7:48
add a comment |
But if a user puts in some values that are not valid, wouldn't it just look like they just lost their values?
– Faller
Mar 25 at 20:41
@Faller . . . Are you trying to prevent users from changing values that add up to 1?
– Gordon Linoff
Mar 25 at 21:04
Users enter components of a mixture in percentages. I'm making sure those components add up to 1 (100%).
– Faller
Mar 25 at 21:59
@Faller, in database the best approach you can get is a mix or this computed column and the constraint to prevent sums greater than 1, the rest needs to be done in business layer...
– Daniel Brughera
Mar 26 at 7:48
But if a user puts in some values that are not valid, wouldn't it just look like they just lost their values?
– Faller
Mar 25 at 20:41
But if a user puts in some values that are not valid, wouldn't it just look like they just lost their values?
– Faller
Mar 25 at 20:41
@Faller . . . Are you trying to prevent users from changing values that add up to 1?
– Gordon Linoff
Mar 25 at 21:04
@Faller . . . Are you trying to prevent users from changing values that add up to 1?
– Gordon Linoff
Mar 25 at 21:04
Users enter components of a mixture in percentages. I'm making sure those components add up to 1 (100%).
– Faller
Mar 25 at 21:59
Users enter components of a mixture in percentages. I'm making sure those components add up to 1 (100%).
– Faller
Mar 25 at 21:59
@Faller, in database the best approach you can get is a mix or this computed column and the constraint to prevent sums greater than 1, the rest needs to be done in business layer...
– Daniel Brughera
Mar 26 at 7:48
@Faller, in database the best approach you can get is a mix or this computed column and the constraint to prevent sums greater than 1, the rest needs to be done in business layer...
– Daniel Brughera
Mar 26 at 7:48
add a comment |
Here is a working version of solution
Here is table DDL
create table dbo.test(
id int,
fkid bigint,
value decimal(4,2)
);
The function definition
CREATE FUNCTION[dbo].[CheckSumTarget](@ID bigint)
RETURNS bit
AS BEGIN
DECLARE @Res decimal(4,2)
SELECT @Res = case when sum(value) > 1 then 1 else 0 end
FROM dbo.Test AS t
WHERE t.FKID = @ID
RETURN @Res
END
And the constraint defintion
ALTER TABLE dbo.Test WITH CHECK ADD CONSTRAINT [CK_Target_Sum] CHECK ([dbo].[CheckSumTarget]([FKID]) <> 1)
In your example
insert into dbo.test values (1, 2, 0.5);
insert into dbo.test values (1, 2, 0.4);
-- The following insert will fail, like you expect
insert into dbo.test values (1, 2, 0.2);
Note: This solution will be broken by UPDATE statement (as pointed out by 'Daniel Brughera') however that is a known behaviour. A better and common approach is use of trigger. You may want to explore that.
This constraint can be broken with an update
– Daniel Brughera
Mar 25 at 21:52
Yes the update will break this. The better solution is use of a trigger
– Gro
Mar 25 at 22:07
The check can work if you add the value column to the constraint, it’s failing because the fkid wasn’t updated, so, the constraint is not checked again, my approach works for that, but I agree that is not the best solution
– Daniel Brughera
Mar 25 at 22:29
Check my function and the update doesn’t break it
– Daniel Brughera
Mar 25 at 22:30
But this only works for greater than. I need it to add to 1 exactly.
– Faller
Mar 25 at 22:44
|
show 2 more comments
Here is a working version of solution
Here is table DDL
create table dbo.test(
id int,
fkid bigint,
value decimal(4,2)
);
The function definition
CREATE FUNCTION[dbo].[CheckSumTarget](@ID bigint)
RETURNS bit
AS BEGIN
DECLARE @Res decimal(4,2)
SELECT @Res = case when sum(value) > 1 then 1 else 0 end
FROM dbo.Test AS t
WHERE t.FKID = @ID
RETURN @Res
END
And the constraint defintion
ALTER TABLE dbo.Test WITH CHECK ADD CONSTRAINT [CK_Target_Sum] CHECK ([dbo].[CheckSumTarget]([FKID]) <> 1)
In your example
insert into dbo.test values (1, 2, 0.5);
insert into dbo.test values (1, 2, 0.4);
-- The following insert will fail, like you expect
insert into dbo.test values (1, 2, 0.2);
Note: This solution will be broken by UPDATE statement (as pointed out by 'Daniel Brughera') however that is a known behaviour. A better and common approach is use of trigger. You may want to explore that.
This constraint can be broken with an update
– Daniel Brughera
Mar 25 at 21:52
Yes the update will break this. The better solution is use of a trigger
– Gro
Mar 25 at 22:07
The check can work if you add the value column to the constraint, it’s failing because the fkid wasn’t updated, so, the constraint is not checked again, my approach works for that, but I agree that is not the best solution
– Daniel Brughera
Mar 25 at 22:29
Check my function and the update doesn’t break it
– Daniel Brughera
Mar 25 at 22:30
But this only works for greater than. I need it to add to 1 exactly.
– Faller
Mar 25 at 22:44
|
show 2 more comments
Here is a working version of solution
Here is table DDL
create table dbo.test(
id int,
fkid bigint,
value decimal(4,2)
);
The function definition
CREATE FUNCTION[dbo].[CheckSumTarget](@ID bigint)
RETURNS bit
AS BEGIN
DECLARE @Res decimal(4,2)
SELECT @Res = case when sum(value) > 1 then 1 else 0 end
FROM dbo.Test AS t
WHERE t.FKID = @ID
RETURN @Res
END
And the constraint defintion
ALTER TABLE dbo.Test WITH CHECK ADD CONSTRAINT [CK_Target_Sum] CHECK ([dbo].[CheckSumTarget]([FKID]) <> 1)
In your example
insert into dbo.test values (1, 2, 0.5);
insert into dbo.test values (1, 2, 0.4);
-- The following insert will fail, like you expect
insert into dbo.test values (1, 2, 0.2);
Note: This solution will be broken by UPDATE statement (as pointed out by 'Daniel Brughera') however that is a known behaviour. A better and common approach is use of trigger. You may want to explore that.
Here is a working version of solution
Here is table DDL
create table dbo.test(
id int,
fkid bigint,
value decimal(4,2)
);
The function definition
CREATE FUNCTION[dbo].[CheckSumTarget](@ID bigint)
RETURNS bit
AS BEGIN
DECLARE @Res decimal(4,2)
SELECT @Res = case when sum(value) > 1 then 1 else 0 end
FROM dbo.Test AS t
WHERE t.FKID = @ID
RETURN @Res
END
And the constraint defintion
ALTER TABLE dbo.Test WITH CHECK ADD CONSTRAINT [CK_Target_Sum] CHECK ([dbo].[CheckSumTarget]([FKID]) <> 1)
In your example
insert into dbo.test values (1, 2, 0.5);
insert into dbo.test values (1, 2, 0.4);
-- The following insert will fail, like you expect
insert into dbo.test values (1, 2, 0.2);
Note: This solution will be broken by UPDATE statement (as pointed out by 'Daniel Brughera') however that is a known behaviour. A better and common approach is use of trigger. You may want to explore that.
edited Mar 25 at 22:09
answered Mar 25 at 21:12
GroGro
5304 silver badges9 bronze badges
5304 silver badges9 bronze badges
This constraint can be broken with an update
– Daniel Brughera
Mar 25 at 21:52
Yes the update will break this. The better solution is use of a trigger
– Gro
Mar 25 at 22:07
The check can work if you add the value column to the constraint, it’s failing because the fkid wasn’t updated, so, the constraint is not checked again, my approach works for that, but I agree that is not the best solution
– Daniel Brughera
Mar 25 at 22:29
Check my function and the update doesn’t break it
– Daniel Brughera
Mar 25 at 22:30
But this only works for greater than. I need it to add to 1 exactly.
– Faller
Mar 25 at 22:44
|
show 2 more comments
This constraint can be broken with an update
– Daniel Brughera
Mar 25 at 21:52
Yes the update will break this. The better solution is use of a trigger
– Gro
Mar 25 at 22:07
The check can work if you add the value column to the constraint, it’s failing because the fkid wasn’t updated, so, the constraint is not checked again, my approach works for that, but I agree that is not the best solution
– Daniel Brughera
Mar 25 at 22:29
Check my function and the update doesn’t break it
– Daniel Brughera
Mar 25 at 22:30
But this only works for greater than. I need it to add to 1 exactly.
– Faller
Mar 25 at 22:44
This constraint can be broken with an update
– Daniel Brughera
Mar 25 at 21:52
This constraint can be broken with an update
– Daniel Brughera
Mar 25 at 21:52
Yes the update will break this. The better solution is use of a trigger
– Gro
Mar 25 at 22:07
Yes the update will break this. The better solution is use of a trigger
– Gro
Mar 25 at 22:07
The check can work if you add the value column to the constraint, it’s failing because the fkid wasn’t updated, so, the constraint is not checked again, my approach works for that, but I agree that is not the best solution
– Daniel Brughera
Mar 25 at 22:29
The check can work if you add the value column to the constraint, it’s failing because the fkid wasn’t updated, so, the constraint is not checked again, my approach works for that, but I agree that is not the best solution
– Daniel Brughera
Mar 25 at 22:29
Check my function and the update doesn’t break it
– Daniel Brughera
Mar 25 at 22:30
Check my function and the update doesn’t break it
– Daniel Brughera
Mar 25 at 22:30
But this only works for greater than. I need it to add to 1 exactly.
– Faller
Mar 25 at 22:44
But this only works for greater than. I need it to add to 1 exactly.
– Faller
Mar 25 at 22:44
|
show 2 more comments
Your actual approach will work this way.....
- You insert the firts component, the value must be 1
- You try to insert a second component, it will be rejected because your sum is already 1
- You update the existing component to .85
- You insert the next component, the value must be .15
- You back to step 2. with the third component
Since your constraint only takes care of the FKID column, it will be possible, and you may think that is working....
But.... if you left the process in step 3. your sum is not equal to 1 and is impossible for the constraint to foresee if you will insert the next value or not, even worst, you can update any value to be greater than 1 and it will be accepted.
If you add the value column to your constraint, it will prevent those updates, but you will never be able to go beyond step 1.
Personally I would't do that, but here you can get an approach
- Use the computed column suggested by Gordon on your parent table. With computed columns you will always get the actual value, so, the parent wont be valid until the sum is equal to one
- Use this solution to prevent the value to be greater than 1, so, at least you will be sure that any non valid parent is because a component is missing, that can be helpful for your business layer
- As I mentioned in one comment, the rest of the logic belongs to the business and ui layers
Note as you can see the id and value parameters are not used in the function, but I need them to call them when I create the constraint, that way the constraint will validate updates too
CREATE TABLE ttest (id int, fkid int, value float)
go
create FUNCTION [dbo].[CheckSumTarget](@id int, @fkid int, @value float)
RETURNS FLOAT
AS BEGIN
DECLARE @Res float
SELECT @Res = sum(value)
FROM dbo.ttest AS t
WHERE t.FKID = @fkid
RETURN @Res
END
GO
ALTER TABLE dbo.ttest WITH CHECK ADD CONSTRAINT [CK_Target_Sum] CHECK (([dbo].[CheckSumTarget](id,[FKID],value)<=(1.0)))
add a comment |
Your actual approach will work this way.....
- You insert the firts component, the value must be 1
- You try to insert a second component, it will be rejected because your sum is already 1
- You update the existing component to .85
- You insert the next component, the value must be .15
- You back to step 2. with the third component
Since your constraint only takes care of the FKID column, it will be possible, and you may think that is working....
But.... if you left the process in step 3. your sum is not equal to 1 and is impossible for the constraint to foresee if you will insert the next value or not, even worst, you can update any value to be greater than 1 and it will be accepted.
If you add the value column to your constraint, it will prevent those updates, but you will never be able to go beyond step 1.
Personally I would't do that, but here you can get an approach
- Use the computed column suggested by Gordon on your parent table. With computed columns you will always get the actual value, so, the parent wont be valid until the sum is equal to one
- Use this solution to prevent the value to be greater than 1, so, at least you will be sure that any non valid parent is because a component is missing, that can be helpful for your business layer
- As I mentioned in one comment, the rest of the logic belongs to the business and ui layers
Note as you can see the id and value parameters are not used in the function, but I need them to call them when I create the constraint, that way the constraint will validate updates too
CREATE TABLE ttest (id int, fkid int, value float)
go
create FUNCTION [dbo].[CheckSumTarget](@id int, @fkid int, @value float)
RETURNS FLOAT
AS BEGIN
DECLARE @Res float
SELECT @Res = sum(value)
FROM dbo.ttest AS t
WHERE t.FKID = @fkid
RETURN @Res
END
GO
ALTER TABLE dbo.ttest WITH CHECK ADD CONSTRAINT [CK_Target_Sum] CHECK (([dbo].[CheckSumTarget](id,[FKID],value)<=(1.0)))
add a comment |
Your actual approach will work this way.....
- You insert the firts component, the value must be 1
- You try to insert a second component, it will be rejected because your sum is already 1
- You update the existing component to .85
- You insert the next component, the value must be .15
- You back to step 2. with the third component
Since your constraint only takes care of the FKID column, it will be possible, and you may think that is working....
But.... if you left the process in step 3. your sum is not equal to 1 and is impossible for the constraint to foresee if you will insert the next value or not, even worst, you can update any value to be greater than 1 and it will be accepted.
If you add the value column to your constraint, it will prevent those updates, but you will never be able to go beyond step 1.
Personally I would't do that, but here you can get an approach
- Use the computed column suggested by Gordon on your parent table. With computed columns you will always get the actual value, so, the parent wont be valid until the sum is equal to one
- Use this solution to prevent the value to be greater than 1, so, at least you will be sure that any non valid parent is because a component is missing, that can be helpful for your business layer
- As I mentioned in one comment, the rest of the logic belongs to the business and ui layers
Note as you can see the id and value parameters are not used in the function, but I need them to call them when I create the constraint, that way the constraint will validate updates too
CREATE TABLE ttest (id int, fkid int, value float)
go
create FUNCTION [dbo].[CheckSumTarget](@id int, @fkid int, @value float)
RETURNS FLOAT
AS BEGIN
DECLARE @Res float
SELECT @Res = sum(value)
FROM dbo.ttest AS t
WHERE t.FKID = @fkid
RETURN @Res
END
GO
ALTER TABLE dbo.ttest WITH CHECK ADD CONSTRAINT [CK_Target_Sum] CHECK (([dbo].[CheckSumTarget](id,[FKID],value)<=(1.0)))
Your actual approach will work this way.....
- You insert the firts component, the value must be 1
- You try to insert a second component, it will be rejected because your sum is already 1
- You update the existing component to .85
- You insert the next component, the value must be .15
- You back to step 2. with the third component
Since your constraint only takes care of the FKID column, it will be possible, and you may think that is working....
But.... if you left the process in step 3. your sum is not equal to 1 and is impossible for the constraint to foresee if you will insert the next value or not, even worst, you can update any value to be greater than 1 and it will be accepted.
If you add the value column to your constraint, it will prevent those updates, but you will never be able to go beyond step 1.
Personally I would't do that, but here you can get an approach
- Use the computed column suggested by Gordon on your parent table. With computed columns you will always get the actual value, so, the parent wont be valid until the sum is equal to one
- Use this solution to prevent the value to be greater than 1, so, at least you will be sure that any non valid parent is because a component is missing, that can be helpful for your business layer
- As I mentioned in one comment, the rest of the logic belongs to the business and ui layers
Note as you can see the id and value parameters are not used in the function, but I need them to call them when I create the constraint, that way the constraint will validate updates too
CREATE TABLE ttest (id int, fkid int, value float)
go
create FUNCTION [dbo].[CheckSumTarget](@id int, @fkid int, @value float)
RETURNS FLOAT
AS BEGIN
DECLARE @Res float
SELECT @Res = sum(value)
FROM dbo.ttest AS t
WHERE t.FKID = @fkid
RETURN @Res
END
GO
ALTER TABLE dbo.ttest WITH CHECK ADD CONSTRAINT [CK_Target_Sum] CHECK (([dbo].[CheckSumTarget](id,[FKID],value)<=(1.0)))
edited Mar 26 at 8:14
answered Mar 25 at 21:48
Daniel BrugheraDaniel Brughera
1,4731 gold badge3 silver badges14 bronze badges
1,4731 gold badge3 silver badges14 bronze badges
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55345784%2fconstrain-sumcolumn-to-1-by-some-group-id%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown