" If condition" as one of the constraints to a Column Field? - sql

I have a Sales tax column in one of my SQL Table where Data is stored.
I was wondering is it possible to place an constraint on the table itself for the Sales Tax
Column saying " if > June 2008 tax is 2 % " else "tax is 4 %"?
Should that come from stored procs related to that Table?

If you want to make sure that the column 'tax' is 2 or 4 depending on the month (e.g., month 9 = September), then you could do this:
ALTER TABLE SomeTable
ADD CONSTRAINT CK_SalesTax
CHECK ((MONTH(GETDATE()) = 9 AND SalesTax = 2) OR (MONTH(GETDATE()) != 9 AND SalesTax = 4))
Obviously, vary for your conditions. e.g., to test for dates after June 2008, it's a bit simpler.
(GETDATE() >= '1 June 2008' AND SalesTax = 2)
You should be able to build this into a CHECK constraint of using a similar mechanism as I've dropped in the first example.
Note this only checks the value that put in to the table. It won't auto-populate. As other people have noted, if you want auto-population, you need a trigger.

Do you want the tax to be auto-populated?
Constraints only perform verification, not population of data, which can be done by stored procs or triggers.

You probably need to use a trigger rather than a constraint. An AFTER INSERT trigger should do the trick.

You could use a constraint to achieve this effect...
pseudo-SQL...
(YourDate >= '6/1/08' and YourTaxData = 0.02) or (YourTaxData = 0.04)
You might consider instead using a table to host the tax values and using your queries to pull the appropriate tax value for a given date/location. That's more scalable than the constraint.

here is a simple way you can alter or create a new table
create table #test (
Date datetime,
amount money,
tax as case when date > '06/01/08' then convert(decimal(10,2),4.00) else convert(decimal(10,2),2.00) end,
)
insert into #test
select '05/01/08', 10.00
insert into #test
select '07/01/08', 10.00
select * from #test

Related

I have a table where I need to update or insert depending on field paramaters

I have spent many hours researching this problem and trying various solutions but I never quite find a suitable solution for my specific problem. I am new to SQL and some of the examples are confusing as well.
So here is my dilemma. I have a equipment table that tracks oil changes for specific units in a database. The table looks like this:
**id UnitID Posted_On Date_Completed Note OverDueBy**
1 BT-109F 2019-02-04 2019-02-14 Hrs Overdue 23
1 BT-108G 2020-01-17 2020-01-22 Days Overdue 12
1 BT-122K 2020-01-02 2020-01-16 Days Overdue 12
1 BT-109F 2019-02-04 Days Overdue 3
The example records above need to be created or updated by the query. The date completed is entered manually by the technician when he has completed the oil change.
What I want the query to do is, Check to see if a specific Unit has a record where the 'Date_Completed' field is empty, and if so update the 'OverDueBy' field to reflect the new value. If all the records for the specified Unit have the 'Date_Completed' fields filled in, then the query should create a new record will all fields filled in except for the 'Date_Completed' field.
Can anyone help me construct such a query?
Thanks
Clan
First create a unique partial index for the column UnitID:
CREATE UNIQUE INDEX idx_unit ON tablename(UnitID)
WHERE Date_Completed IS NULL;
so that only 1 row with Date_Completed=null is allowed for each UnitID.
So a statement like this:
INSERT INTO tablename(id, UnitID, Posted_On, Date_Completed, Note, OverDueBy)
VALUES (?, 'BT-109F', ?, null, ?, ?)
ON CONFLICT(UnitID) WHERE Date_Completed IS NULL DO UPDATE
SET OverDueBy = ?;
will insert the new values only if there is no row already for UnitID='BT-109F' with null in Date_Completed.
But if there is such a row then it will update the column OverDueBy.
I'm not sure what values you want to insert or what will be the updated value so replace the ? with the appropriate values.
Firstly I would use a view rather than a table to store any calculated data - it reduces storage overheads and will update the calculation every time the view is opened.
If you're using SQLite you should be able to get the overdue by subtracting the Posted_On from its function to return today's date something like date('now') or julianday('now') - read up on and test the functions to ensure it does what you want.
So along the lines of:-
create view MyView as select *, julianday('now') - julianday(Posted_On) as OverDueBy from ClansTable where Date_Completed is null;
If you want to store a snapshot you can always create a table from a view in any case:-
create table MyStoredOverduesOn4thFeb as select * from MyView;
You can find your units that have all Date_Completed and create a single new record like so:-
Create table CompletedUnits as select id, UnitID, max(posted_on) as latest_posted_on, '' as Date_Completed from ClansTable group by id, UnitID having count(*) = count(Date_Complete);
Test this SQL and see if you can get it working - note I've created a text field for the date. Apparently there is no date/datetime data type as such:-
https://www.sqlitetutorial.net/sqlite-date/
Hope this helps,
Phil
I think you need something like this:
MERGE INTO EQUIPMENT A
USING (SELECT * FROM EQUIPMENT B WHERE DATE_COMPLETED IS NULL) C
ON (A.UNITID=C.UNITID)
WHEN MATCHED THEN UPDATE SET A.OVERDUEBY="new value"
WHEN NOT MATCHED THEN INSERT (A.id,A.UnitID,A.Posted_On,A.Date_Completed,A.Note,A.OverDueBy)
VALUES (C.id,C.UnitID,C.Posted_On,NULL,C.Note,C.OverDueBy)
Not sure where new values from update will come from. It's not clear in your question. But something like this could work.

Trigger sum of two columns into 3rd SQL

I am trying to set a trigger in Microsoft Server Manager where a 3rd gets populated by a trigger
Eg. I have a table that contains
Column 1: Amount
Column 2: AdminFee
Column 3: TotalAmount
I need each new row in column3 (total amount) to be populated by Amount + AdminFee
I have the following script but it is not updating Column 3
CREATE TRIGGER UpdateActualAmount
ON Event
AFTER INSERT
AS
BEGIN
UPDATE BankTransaction
SET ActualAmount = Amount + AdminFee
END
GO
Can anyone let me know Where I am going wrong?
Run this one time:
ALTER TABLE BankTransaction DROP COLUMN ActualAmount;
ALTER TABLE BankTransaction ADD ActualAmount as (Amount+AdminFee)
Though tbh I'd be doing this in the front end as I don't really feel this kind of calculation has any business case for being part of the table..
If you're desperate to store the result of this sim as a table column and you want to index/query it, then make it a PERSISTED column..

t-SQL - constraint on one column that has multiple conditions

I am currently re structuring a poorly designed database, one of the things I want to do for integrity purposes is make a certain record unique dependent on a few variables.
The table I am using is Quotes, the column in question is the Quote number, what I need is for this to be unique to each Company and group, so for example Quote001 should be unique unless there is a new company / group used.
So you could have Quote001 with company1 and group1, but then if a new quote is made with company1 and group1 the new quote number should be Quote002. However if Company2 and group1 make a quote it should be back to Quote001.
I am unsure as to how to achieve this most effectively, using constraints in the database.
Thanks,
David
If you already have an identity column on this table, I would use it to create a computed column for the qoute number. If you don't alrady have one, you can add it.
To do that, first you need to define a UDF that will do the calculation for you:
CREATE FUNCTION dbo.CalculateQuoteNumber(#id int, #Company int, #Group int)
RETURNS int
AS
BEGIN
RETURN
(
SELECT COUNT(*)
FROM YourTable
WHERE Company = #Company
AND [Group] = #Group
AND id <= #id
)
END
GO
Then, you add the Quote number as a calculated column:
ALTER TABLE YourTable
ADD QuoteNumber as dbo.CalculateQuoteNumber(id, Company, [Group])
Now sql server will do the calculation for you, and you are safe since computed columns can't be inserted to or updated by the users.
You can see a live demo on rextester.
You need a unique constraint.
ALTER TABLE Quotes
ADD CONSTRAINT ucQuote UNIQUE (QuoteNumber, Company, Group)

Copy column with mathematic SQL Server

I'm new to SQL Server. I have column with value of product, now I want to add column value + tax (tax = 10% value) on the same table. Any suggestion how to do this the fastest way or should I insert 1 by 1? Can I just copy value column and add some mathematics ? If I can do that can someone show how it work? Thanks.
If the tax is always the same, you can use a computed column:
alter t add value_plus_tax as (value * 1.1);
This calculates the value whenever you need it. Otherwise, you should add the column explicitly and update it:
alter t add value_plus_tax decimal(10, 2); -- or whatever
update t
set value_plus_tax = value * 1.1;
If your tax rate can change, you can store the rate in a separate table and use a view that joins the two tables to retrieve the data...
CREATE TABLE TaxRate (
[Percent] TINYINT
)
GO
CREATE VIEW ValuesWithTax AS
SELECT *, [Value] * [Percent] / 100 ValueWithTax FROM [Values]
CROSS JOIN TaxRate
If tax rate is not a fix value, you can add a column to save tax rate and a computed column to save total value
ALTER TABLE table1 add tax_rate decimal(19,4) DEFAULT(0.1) WITH VALUES
ALTER TABLE table1 add toatal_value as ([value](1+tax_rate))
Add computed column like (having all calculation).
Ie : Below example i have considered sum of value and tax column you can do any calculation (Make sure the calculation should not throw exception consider boundary condition ) .
ALTER TABLE dbo.tableName ADD RetailValue AS (value+tax );
you can make it persisted computed column too.

Adding a column which uses other column fields as operands for operation like addition and percentage calculation

ALTER PROCEDURE [dbo].[Sp_TotalMarks]
AS
BEGIN
SELECT Student_Id, Stu_Name, Maths, English, Hindi,
(Maths + English + Hindi) AS 'Total',
CAST(CAST((Maths + English + Hindi) AS NUMERIC(8,2)) / 300 * 100 AS NUMERIC(8,2)) AS 'Percentage'
FROM tbl_Marks
END
This is the procedure which I am using to display percentage.
If there are 100 students in a class and I want to display the percentage of each one of them then the SP which dynamically calculates the %age and returns the answer , will be time consuming. Earlier I was trying to add a column of percentage in tbl_Marks itself.Is it possible to implement trigger in the store procedure which is called on 'INSERT' or 'UPDATE' operation on the tbl_Marks. I have never used trigger actually. If you could explain me the solution of this problem with a query It would be great. Thanks in advance.
A computed column can use data from other columns of the table to calculate a value for the column to which it belongs.Also a computed column is a virtual column that is not physically stored in the table, unless the column is marked PERSISTED.
So alter your table definition as:
ALTER TABLE tbl_Marks ADD total AS (Maths + English + Hindi) PERSISTED;
ALTER TABLE tbl_Marks ADD Percentage AS CAST(CAST((Maths + English + Hindi) AS NUMERIC(8,2)) / 300 * 100 AS NUMERIC(8,2)) PERSISTED;
This will add two columns to the table which will reflect the computed values on each update or insert.
You can check the DEMO here. Hope this helps!!!