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;








1















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).
dbo.Test



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.










share|improve this question




























    1















    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).
    dbo.Test



    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.










    share|improve this question
























      1












      1








      1








      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).
      dbo.Test



      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.










      share|improve this question














      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).
      dbo.Test



      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






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Mar 25 at 20:18









      FallerFaller

      6092 gold badges8 silver badges22 bronze badges




      6092 gold badges8 silver badges22 bronze badges






















          3 Answers
          3






          active

          oldest

          votes


















          2














          This approach seems fraught with problems.



          I would suggest another approach, starting with two tables:




          • aggregates, so "fkid" should really be aggregate_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;





          share|improve this answer























          • 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



















          1














          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.






          share|improve this answer

























          • 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


















          1














          Your actual approach will work this way.....



          1. You insert the firts component, the value must be 1

          2. You try to insert a second component, it will be rejected because your sum is already 1

          3. You update the existing component to .85

          4. You insert the next component, the value must be .15

          5. 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



          1. 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

          2. 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

          3. 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)))





          share|improve this answer



























            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
            );



            );













            draft saved

            draft discarded


















            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









            2














            This approach seems fraught with problems.



            I would suggest another approach, starting with two tables:




            • aggregates, so "fkid" should really be aggregate_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;





            share|improve this answer























            • 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
















            2














            This approach seems fraught with problems.



            I would suggest another approach, starting with two tables:




            • aggregates, so "fkid" should really be aggregate_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;





            share|improve this answer























            • 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














            2












            2








            2







            This approach seems fraught with problems.



            I would suggest another approach, starting with two tables:




            • aggregates, so "fkid" should really be aggregate_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;





            share|improve this answer













            This approach seems fraught with problems.



            I would suggest another approach, starting with two tables:




            • aggregates, so "fkid" should really be aggregate_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;






            share|improve this answer












            share|improve this answer



            share|improve this answer










            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


















            • 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














            1














            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.






            share|improve this answer

























            • 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















            1














            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.






            share|improve this answer

























            • 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













            1












            1








            1







            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.






            share|improve this answer















            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.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            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

















            • 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











            1














            Your actual approach will work this way.....



            1. You insert the firts component, the value must be 1

            2. You try to insert a second component, it will be rejected because your sum is already 1

            3. You update the existing component to .85

            4. You insert the next component, the value must be .15

            5. 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



            1. 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

            2. 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

            3. 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)))





            share|improve this answer





























              1














              Your actual approach will work this way.....



              1. You insert the firts component, the value must be 1

              2. You try to insert a second component, it will be rejected because your sum is already 1

              3. You update the existing component to .85

              4. You insert the next component, the value must be .15

              5. 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



              1. 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

              2. 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

              3. 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)))





              share|improve this answer



























                1












                1








                1







                Your actual approach will work this way.....



                1. You insert the firts component, the value must be 1

                2. You try to insert a second component, it will be rejected because your sum is already 1

                3. You update the existing component to .85

                4. You insert the next component, the value must be .15

                5. 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



                1. 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

                2. 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

                3. 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)))





                share|improve this answer















                Your actual approach will work this way.....



                1. You insert the firts component, the value must be 1

                2. You try to insert a second component, it will be rejected because your sum is already 1

                3. You update the existing component to .85

                4. You insert the next component, the value must be .15

                5. 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



                1. 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

                2. 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

                3. 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)))






                share|improve this answer














                share|improve this answer



                share|improve this answer








                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



























                    draft saved

                    draft discarded
















































                    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.




                    draft saved


                    draft discarded














                    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





















































                    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







                    Popular posts from this blog

                    Kamusi Yaliyomo Aina za kamusi | Muundo wa kamusi | Faida za kamusi | Dhima ya picha katika kamusi | Marejeo | Tazama pia | Viungo vya nje | UrambazajiKuhusu kamusiGo-SwahiliWiki-KamusiKamusi ya Kiswahili na Kiingerezakuihariri na kuongeza habari

                    Swift 4 - func physicsWorld not invoked on collision? The Next CEO of Stack OverflowHow to call Objective-C code from Swift#ifdef replacement in the Swift language@selector() in Swift?#pragma mark in Swift?Swift for loop: for index, element in array?dispatch_after - GCD in Swift?Swift Beta performance: sorting arraysSplit a String into an array in Swift?The use of Swift 3 @objc inference in Swift 4 mode is deprecated?How to optimize UITableViewCell, because my UITableView lags

                    Access current req object everywhere in Node.js ExpressWhy are global variables considered bad practice? (node.js)Using req & res across functionsHow do I get the path to the current script with Node.js?What is Node.js' Connect, Express and “middleware”?Node.js w/ express error handling in callbackHow to access the GET parameters after “?” in Express?Modify Node.js req object parametersAccess “app” variable inside of ExpressJS/ConnectJS middleware?Node.js Express app - request objectAngular Http Module considered middleware?Session variables in ExpressJSAdd properties to the req object in expressjs with Typescript