I have a table I'm creating for an app I'm making and want to populate a calculated column from an IF statement,I don't know how to write the T-SQL for it and have looked for an answer but can't find
What i'm looking for is basically
IF (Close<=Open)
[CloseLessEqualToOpen == Yes]
ELSE
[CloseLessEqualToOpen == No]
T-SQL
CREATE TABLE [dbo].[LowFloatStocks] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[Date] DATE NOT NULL,
[Ticker] NCHAR (10) NOT NULL,
[PreviousClose] DECIMAL (4, 2) DEFAULT ((4.00)) NOT NULL,
[OpeningPrice] DECIMAL (18, 2) NOT NULL,
[GainPercent] AS (round(([High]-[OpeningPrice])/[OpeningPrice],(4))*(100.0)) PERSISTED NOT NULL,
[GapPercent] AS (round(([OpeningPrice]-[PreviousClose])/[PreviousClose],(4))*(100.0)) PERSISTED NOT NULL,
[Spike] DECIMAL (18, 2) NOT NULL,
[1stSpike%] AS (round(([Spike]-[OpeningPrice])/[OpeningPrice],(4))*(100.0)) PERSISTED NOT NULL,
[High] DECIMAL (18, 2) NOT NULL,
[HighPercent] AS (round(([High]-[PreviousClose])/[PreviousClose],(4))*(100.0)) PERSISTED NOT NULL,
[Low] DECIMAL (18, 2) NOT NULL,
[LowPercent] AS (round(([Low]-[PreviousClose])/[PreviousClose],(4))*(100.0)) PERSISTED NOT NULL,
[Close] DECIMAL (18, 2) DEFAULT ((4)) NOT NULL,
[ClosePercent] AS (round(([Close]-[PreviousClose])/[PreviousClose],(4))*(100.0)) PERSISTED NOT NULL,
[CloseLessEqualToOpen] NCHAR (3) NULL,
[CloseRed] NCHAR (3) NULL,
[ClosevHigh] AS (round(([High]-[Close])/[Close],(4))*(100)) PERSISTED NOT NULL,
[ClosevOpen] AS (round(([OpeningPrice]-[Close])/[OpeningPrice],(4))*(100.0)) PERSISTED NOT NULL,
[Catalyst] NVARCHAR (50) NOT NULL,
[Float] DECIMAL (18, 3) NOT NULL,
[Dilution] NCHAR (3) NOT NULL,
PRIMARY KEY CLUSTERED ([Id] ASC)
First of all, you need to get a single value to use in your statement:
DECLARE #Close DECIMAL (18, 2);
SET #Close = (SELECT TOP 1 Close FROM [dbo].[LowFloatStocks]);
For above statement, you can also apply WHERE or any other clause based on your need.
Then use SQL IF statement to do your comparisons, this way:
IF(#Close <= Open) -- assuming that Open is declared somewhere else
BEGIN
-- Your logic here
PRINT #Close
END
ELSE
BEGIN
-- Your logic here
PRINT #Close
END
Later you can update your Table this way:
UPDATE
[dbo].[LowFloatStocks]
SET
CloseLessEqualToOpen = ...
WHERE
...
However, there is also a more elegant solution in case if you want to make the calculation process happen automatically.
For that reason you can use Computed Columns:
CREATE TABLE [dbo].[LowFloatStocks]
(
[Close] DECIMAL (18, 2) DEFAULT ((4)) NOT NULL,
[Open] DECIMAL (18, 2) DEFAULT ((4)) NOT NULL,
-- other columns declaration here
[CloseLessEqualToOpen] AS CAST
(
CASE WHEN [Close] <= [Open] THEN 'Yes' ELSE 'No' END AS NVARCHAR(10)
)
)
Related
I have added a compute column, but I get an error when I insert the values, I left out the column name where the compute column is. I read somewhere that you don't include it in your insert.
Msg 110, Level 15, State 1, Line 641 There are fewer columns in the
INSERT statement than values specified in the VALUES clause. The
number of values in the VALUES clause must match the number of columns
specified in the INSERT statement.
CREATE TABLE Voorwerp (
voorwerpnummer BIGINT IDENTITY(30068720558,1)
NOT NULL,
titel VARCHAR(100)
NOT NULL,
beschrijving VARCHAR(max)
NOT NULL,
Startprijs NUMERIC(10,2)
NOT NULL,
Betalingswijze VARCHAR(20)
NOT NULL,
betalinginstructie VARCHAR(80)
NULL,
plaatsnaam VARCHAR(28)
NOT NULL,
Land VARCHAR(35)
NOT NULL,
Looptijd TINYINT DEFAULT ((7))
NOT NULL,
LooptijdbeginDag DATE
NOT NULL,
LooptijdbeginTijdstip TIME
NOT NULL,
Verzendkosten NUMERIC (8,2)
NULL,
verzendinstructies VARCHAR (125)
NULL,
Verkoper VARCHAR (255)
NOT NULL,
Koper VARCHAR (255)
NULL,
LooptijdeindeDag AS DATEADD(DAY,Looptijd,looptijdbeginDag),
looptijdeindeTijdstip TIME
NOT NULL,
VeilingGesloten BIT
NOT NULL,
Verkoopprijs NUMERIC(10,2)
NULL,
INSERT INTO Voorwerp(
[titel],
[beschrijving],
[Startprijs],
[Betalingswijze],
[betalinginstructie],
[plaatsnaam],
[Land],
[Looptijd],
[LooptijdbeginDag],
[LooptijdbeginTijdstip],
[Verzendkosten],
[verzendinstructies],
[Verkoper],
[Koper],
[LooptijdeindeDag],
[looptijdeindeTijdstip],
[VeilingGesloten])
VALUES('Stabiele drum/pi..',
'Stabiele drum/pi..',
50.00,
'Bank',
'Overschrijving moet...',
'New Vennep',
'Nederland',
7,
'2005-05-19',
'09:10:00',
3.50,
'Paket post binnen Nederland',
'Bianca77',
1,
'2005-05-26',
'09:30:00',
1,
500
);
Column LooptijdeindeDag is listed in the column list in the INSERT statement.
You need to remove it and it's corresponding value from the insert statement.
Your insert statement should looks like:
INSERT INTO Voorwerp(
[titel],
[beschrijving],
[Startprijs],
[Betalingswijze],
[betalinginstructie],
[plaatsnaam],
[Land],
[Looptijd],
[LooptijdbeginDag],
[LooptijdbeginTijdstip],
[Verzendkosten],
[verzendinstructies],
[Verkoper],
[Koper],
[looptijdeindeTijdstip],
[VeilingGesloten])
I have this uni assignment where I am given the script for the database as well as the one for the bulk insert and a dataset of about 1.300.000 records. With the database set up, i ran the bulk insert script and I am getting a bulk load data conversion error.
I asked all my friends if they had a similar experience but none of them had the same issue. I tried to look into that, it would seem that what causes this error to happen is the Date field in the MainTable, so i tried to find how to set the default date to DD/MM/YYYY and to use the / instead of -, all I found was some SELECT that formatted the getdate() function and the SET DATEFORMAT dmy command but that didn't fix my errors. I deleted the database and repeated the process at least 3 times now and I'm getting the same error every time.
CREATE TABLE MainTable
(
bookCode int NULL,
bookDt date NULL,
payCode int NULL,
payMethod char(2) NULL,
custCode int NULL,
custName varchar(30) NULL,
custSurname varchar (30) NULL,
custPhone varchar (20) NULL,
staffNo int NULL,
staffName varchar (30) NULL,
staffSurname varchar (30) NULL,
totalCost numeric(19, 2) NULL,
campCode char(3) NULL,
campName varchar (50) NULL,
numOfEmp int NULL,
empNo int NULL,
catCode char (1) NULL,
areaM2 int NULL,
unitCost numeric(4,2) NULL,
startDt date NULL,
endDt date NULL,
noPers int NULL,
costPerRental numeric(19, 2) NULL
);
SET DATEFORMAT dmy
BULK INSERT mainTable
FROM 'C:\DATA\GeneratedData.txt'
WITH (FIRSTROW = 2,FIELDTERMINATOR= ',', ROWTERMINATOR = '\n');
And a couple of records from the dataset:
2615981,14/08/2018,1,CC,990,Christie,BUCKNER,(+30)000-556-7301,5020,Zaria,RACE,45,ROS,Rosibos,200,151,C,30,15,15/08/2018,17/08/2018,1,45
2616347,17/08/2018,3,CA,403,Ashli,MAXWELL,(+30)000-114-8689,5010,Yovonnda,CAZARES,45,ROS,Rosibos,200,151,C,30,15,18/08/2018,20/08/2018,1,45
The error I am getting is this:
Msg 4864, Level 16, State 1, Line 3
Bulk load data conversion error (type mismatch or invalid character for the specified codepage) for row 2, column 2 (bookDt).
I am getting the same error what appears to be every single row in the text file.
Instead of "Set DateFormat dmy", try the following:
Set Language N'british'
Like I said in my comment, it's often easier to insert the data into a string type column in a staging table, and then convert the values afterwards. I've only done this with the Date columns here, but you can do it to the whole lot if you wish:
USE Sandbox;
GO
CREATE SCHEMA stg;
GO
CREATE TABLE stg.MainTable (bookCode int NULL,
bookDt varchar(10) NULL,
payCode int NULL,
payMethod char(2) NULL,
custCode int NULL,
custName varchar(30) NULL,
custSurname varchar(30) NULL,
custPhone varchar(20) NULL,
staffNo int NULL,
staffName varchar(30) NULL,
staffSurname varchar(30) NULL,
totalCost numeric(19, 2) NULL,
campCode char(3) NULL,
campName varchar(50) NULL,
numOfEmp int NULL,
empNo int NULL,
catCode char(1) NULL,
areaM2 int NULL,
unitCost numeric(4, 2) NULL,
startDt varchar(10) NULL,
endDt varchar(10) NULL,
noPers int NULL,
costPerRental numeric(19, 2) NULL);
GO
BULK INSERT stg.MainTable
FROM 'C:\DATA\GeneratedData.txt'
WITH (FIRSTROW = 2,
FIELDTERMINATOR = ',',
ROWTERMINATOR = '\n');
GO
CREATE TABLE dbo.MainTable (bookCode int NULL,
bookDt date NULL,
payCode int NULL,
payMethod char(2) NULL,
custCode int NULL,
custName varchar(30) NULL,
custSurname varchar(30) NULL,
custPhone varchar(20) NULL,
staffNo int NULL,
staffName varchar(30) NULL,
staffSurname varchar(30) NULL,
totalCost numeric(19, 2) NULL,
campCode char(3) NULL,
campName varchar(50) NULL,
numOfEmp int NULL,
empNo int NULL,
catCode char(1) NULL,
areaM2 int NULL,
unitCost numeric(4, 2) NULL,
startDt date NULL,
endDt date NULL,
noPers int NULL,
costPerRental numeric(19, 2) NULL);
GO
INSERT INTO dbo.MainTable
SELECT bookCode,
CONVERT(date, bookDt, 103),
payCode,
payMethod,
custCode,
custName,
custSurname,
custPhone,
staffNo,
staffName,
staffSurname,
totalCost,
campCode,
campName,
numOfEmp,
empNo,
catCode,
areaM2,
unitCost,
CONVERT(date, startDt, 103),
CONVERT(date, endDt, 103),
noPers,
costPerRental
FROM stg.MainTable;
TRUNCATE stg.MainTable;
I want to give a unique ID for every insert statement I make, this is so I can see what rows was inserted together. I prefer that the unique "insert ID" start at 1 and increases by one like the IDENTITY(1,1) for rows.
Is there a easy way like IDENTITY to do that?
CREATE TABLE [dbo].[factTrade]
(
[ID] [int] IDENTITY(1,1) NOT NULL,
[insertedID] [int] NOT NULL,
[quantity] [int] NOT NULL,
[price] [decimal](20, 10) NOT NULL
)
INSERT INTO [dbo].[factTrade] ([insertedID], [quantity], [price])
VALUES (1, 6, 2.5), (1, 4, 3.7), (1, 3, 4.1), (1, 7, 8.5),
INSERT INTO [dbo].[factTrade] ([insertedID], [quantity], [price])
VALUES (2, 5, 5.2), (2, 1, 4.6)
This isn't the solution you asked for, but you could add a column with a default timestamp to find all rows inserted at the same time.
ALTER TABLE dbo.factTrade
ADD InsertDate DATETIME NOT NULL DEFAULT (GETDATE())
Guids are handy for things like that.
declare #insertid uniqueidentifier = newid();
CREATE TABLE [dbo].[factTrade](
[ID] [int] IDENTITY(1,1) NOT NULL,
[insertedID] [int] NOT NULL,
[quantity] [int] NOT NULL,
[price] [decimal](20, 10) NOT NULL,
[insertid] [uniqueidentifier] not null
)
INSERT INTO [dbo].[factTrade]
([insertedID]
,[quantity]
,[price]
,[insertid]
)
VALUES
(1, 6, 2.5,#insertid),
(1, 4, 3.7,#insertid),
(1, 3, 4.1,#insertid),
(1, 7, 8.5,#insertid)
set #insertid = newid(); --get another guid
INSERT INTO [dbo].[factTrade]
([insertedID]
,[quantity]
,[price]
,[insertid]
)
VALUES
(2, 5, 5.2,#insertid),
(2, 1, 4.6,#insertid)
If you need an integer value, then you can create another table:
CREATE TABLE inserts ([ID] INT IDENTITY(1,1)...)
Then from your app, insert a row into this, then use the generated identity value (SCOPE_IDENTITY()).
INSERT inserts DEFAULT VALUES;
SELECT #insertId = SCOPE_IDENTITY();
This is what I ended up doing, thank you for all the suggestions and comments.
DECLARE #insertedID INT
CREATE TABLE [dbo].[factTrade]
(
[ID] [int] IDENTITY(1,1) NOT NULL,
[insertedID] [int] NOT NULL,
[quantity] [int] NOT NULL,
[price] [decimal](20, 10) NOT NULL
)
CREATE SEQUENCE [dbo].[factTradeInsertedID] AS INT
START WITH 1
INCREMENT BY 1
SET #insertedID = NEXT VALUE FOR [dbo].[factTradeInsertedID] --1
INSERT INTO [dbo].[factTrade]
([insertedID]
,[quantity]
,[price])
VALUES
(#insertedID, 6, 2.5)
,(#insertedID, 4, 3.7)
,(#insertedID, 3, 4.1)
,(#insertedID, 7, 8.5)
SET #insertedID = NEXT VALUE FOR [dbo].[factTradeInsertedID] --2
INSERT INTO [dbo].[factTrade]
([insertedID]
,[quantity]
,[price])
VALUES
(#insertedID, 5, 5.2)
,(#insertedID, 1, 4.6)
I have a table with two date columns, both allow nulls.
if FileDate is not null then AsOfDate needs to equal (FileDate - Offset) where Offset is a integer column with a default of zero.
Here is my table def:
CREATE TABLE [import].[CMAR_GLXXXX](
[FileDate] [date] NULL,
[LoadDTM] [date] NULL,
[AsOfDate] [date] NULL,
[AccountNumber] [varchar](50) NOT NULL,
[CostCenter] [varchar](50) NOT NULL,
[OffSet] [int] default (0) NOT NULL,
[Value] [decimal](10,2) NOT NULL
) ON [PRIMARY]
I tried using the following:
(case when [File] IS NULL then NULL else dateadd(day,(-1 * [Offset]),[FileDate]) end)
Unfortunately the computed column error dialog doesn't display much help in troubleshooting the expression.
Any ideas?
A case expression is perfectly valid here but not needed for your desired output. Let sql server handle NULLS naturally.
dateadd(day,(-1 * x),[d1])
--EDIT--
To demonstrate here is a table definition. Seems this does exactly what you are looking for.
create table #Something
(
x int
, d1 datetime
, compCol as dateadd(day, (-1 * x), [d1])
)
insert #Something
select 3, null union all
select 4, '2016-01-01'
select *
from #Something
I am assuming your expression is correct. just use correct syntax for case.
CREATE TABLE CMAR_GLXXXX(
[FileDate] [date] NULL,
[LoadDTM] [date] NULL,
[AsOfDate] [date] NULL,
[AccountNumber] [varchar](50) NOT NULL,
[CostCenter] [varchar](50) NOT NULL,
[OffSet] [int] default (0) NOT NULL,
[Value] [decimal](10,2) NOT NULL
)
select
(case when [FileDate] IS NULL then NULL else dateadd(day,(-1 * [OffSet]),[FileDate]) end)
from CMAR_GLXXXX
I have the following table in SQL Server:
CREATE TABLE [dbo].[tblTempPo](
[TempPoID] [int] IDENTITY(1,1) NOT NULL,
[guid] AS ([dbo].[GetIdentity]()),
[Qty] [int] NULL,
[MobileBrandID] [int] NULL,
[MobileID] [int] NULL
)
I need to insert the current row number to the guid column every time a new row is added. I tried to use the following function but it's not working as expected:
ALTER FUNCTION GetIdentity()
RETURNS INT AS
BEGIN
RETURN (SELECT top 1 ROW_NUMBER() OVER(ORDER BY TempPoID asc)FROM tblTempPo)
END
Your function GetIdentity() will probably always return 1 but it is not a sure thing because you are using select top 1... without an order by clause.
If you want the highest value returned by row_number() you need to add order by 1 desc which would be the same as doing SELECT count(*) from tblTempPo.
Fixing GetIdentity() like that will not help much in your situation because [guid] AS ([dbo].[GetIdentity]()) will give you a computed column that is evaluated every time you query the table and not when you insert a new row. You will always have the same value for all rows.
You could use a function that takes the TempPoID as a parameter as a computed column.
CREATE FUNCTION GetIdentity(#P int)
RETURNS INT AS
BEGIN
RETURN (SELECT rn
FROM (SELECT TempPoID,
ROW_NUMBER() OVER(ORDER BY TempPoID ASC) AS rn
FROM tblTempPo) AS T
WHERE TempPoID = #P)
END
Table definition:
CREATE TABLE [dbo].[tblTempPo](
[TempPoID] [int] IDENTITY(1,1) NOT NULL primary key,
[guid] as dbo.GetIdentity(TempPoID),
[Qty] [int] NULL,
[MobileBrandID] [int] NULL,
[MobileID] [int] NULL
I have never used this so I can't tell you if it is a good thing to do or not. It might be devastating for your query performance, I just don't know.
I agree with comments and you should change the GUID column name. If you really have to store the TempPoID column twice use computed column. Example:
CREATE TABLE #tblTempPo (
[TempPoID] [int] IDENTITY(1,1) NOT NULL,
[second_id] AS TempPoID,
[Qty] [int] NULL,
[MobileBrandID] [int] NULL,
[MobileID] [int] NULL
)
INSERT INTO #tblTempPo (Qty, MobileBrandID, MobileID) VALUES
(10, 10, 15), (20, 23, 45), (55, 23, 12), (10, 1, 1)
SELECT * FROM #tblTempPo
DROP TABLE #tblTempPo
If you need more complicated approach - use trigger.
It's all no good idea, but if you REALLY need it, try trigger:
create table [dbo].[tblTempPo](
[TempPoID] [int] identity(1,1) NOT NULL,
[guid] int,
[Qty] [int] NULL,
[MobileBrandID] [int] NULL,
[MobileID] [int] NULL
)
go
create trigger [dbo].[tblTempPo_Trig] on [dbo].[tblTempPo] instead of insert as
declare #cnt int
select #cnt = count(*)
from [dbo].[tblTempPo] with(nolock)
insert into [dbo].[tblTempPo]([guid], [Qty], [MobileBrandID], [MobileID])
select #cnt+row_number() over (order by [TempPoID]), [Qty], [MobileBrandID], [MobileID] from inserted
go
insert into [dbo].[tblTempPo]([Qty], [MobileBrandID], [MobileID]) values (0, 0,0), (0, 0,0), (0, 0,0), (0, 0,0)
insert into [dbo].[tblTempPo]([Qty], [MobileBrandID], [MobileID]) values (0, 0,0), (0, 0,0), (0, 0,0), (0, 0,0)
select * from [dbo].[tblTempPo]
go
drop table [dbo].[tblTempPo]
go