SQL Server- How to use data in column for DATEADD - datepart - sql-server

I want to pass data from a variable/ from table column as the 'datepart' when using DATEADD function. Below is snippet of my code where I'm seeing the error as below.
DECLARE #vchstring VARCHAR(20)
SET #vchstring='month'
SELECT DATEADD(#vchstring,1,GETDATE())
I get this error:
Msg 1023, Level 15, State 1, Line 104
Invalid parameter 1 specified for dateadd.
This could be a duplicate, but am not able to find any information.

SQL Server does not support macro substitution. You would either have to use Dynamic SQL or a nested case/IF or even a SELECT
Example
DECLARE #vchstring VARCHAR(20)
SET #vchstring='month'
Select Value
From ( values ('year' ,DATEADD(YEAR ,1,GETDATE()) )
,('month' ,DATEADD(MONTH ,1,GETDATE()) )
,('day' ,DATEADD(DAY ,1,GETDATE()) )
,('hour' ,DATEADD(HOUR ,1,GETDATE()) )
,('minute',DATEADD(MINUTE ,1,GETDATE()) )
) A (inc,value)
Where inc = #vchstring
Returns
Value
2020-06-05 10:09:29.660

Related

SQL: How to refer to a dynamic column name to make calculation

I'd like to update fields while referring to a dynamic column.
The goal is to automate a process because each month the column to refer to changes.
For example it's like having different columns like month1, month2, month3 until month24. Each month, only 1 column needs to be updated but it's a running number that is calculated in another table.
So my question is how to make the query dynamic so that every month i only update the column number that i want and not the other one.
I tried the script below but the following issue comes up
Error converting data type varchar to float.
DECLARE #PromoMonthNumber VARCHAR(60)
DECLARE #PromoMonth VARCHAR(600)
SET #PromoMonthNumber = (SELECT CurrentDemandIndex FROM RidgeSys) --This refer to a number that change all the time
SET #PromoMonth = 'SELECT ABC.PromotionHistory' + #PromoMonthNumber
UPDATE ABC
SET #PromoMonth = table2.promotionhistory
FROM ABC
INNER JOIN (
SELECT Article.code as code, sum(ROUND(#PromoMonth,0)) as promotionhistory
FROM Article
INNER JOIN ABC ON DEF.articlecode = ABC.Articlecode
) as table2
ON ABC.articlecode = table2.code)
Here is your issue:
SELECT Article.code as code, sum(ROUND(#PromoMonth,0)) as promotionhistory
Since #PromoMonth is defined as VARCHAR, if the value is non-numeric, it will fail. Here is an example:
This works fine:
declare #x varchar(100) = '1';
select sum(round(#x,0));
Result:
1
This fails with same error above:
declare #x varchar(100) = 'x';
select sum(round(#x,0));
Result:
Msg 8114, Level 16, State 5, Line 3
Error converting data type varchar to float.
You need to check that the value is numeric before you do the calculation.

Invalid STRING_SPLIT args in SQL Server

I am trying to parse a cell that is data type nvarchar(max) like it is csv in SQL Server 2017. I was hoping to use the STRING_SPLIT return a row of data for each value in the array-like string. However, when I run the following code I get an error.
select this_column
into #t
from that_table
where coordinate_x = 1
and coordinate_y = 7
select * from STRING_SPLIT(#t.this_column, ',')
Msg 4104, Level 16, State 1, Line 16
The multi-part identifier "#t.this_column" could not be bound
Msg 8116, Level 16, State 1, Line 16
Argument data type void type is invalid for argument 1 of string_split function
How can I parse this data?
You can't pass a table to a inline table function, you need to include it in your FROM:
SELECT {YourColumns}
FROM #t T
CROSS APPLY STRING_SPLIT(T.this_column, ',') SS;
You'll want to use a cross apply with your temp table
Here's a working example so you can see how that works:
DECLARE #TestData TABLE
(
[TestData] NVARCHAR(MAX)
);
INSERT INTO #TestData (
[TestData]
)
VALUES ( N'1,2,3,4,5,6,7,8,9');
SELECT [b].[value] FROM #TestData [a]
CROSS APPLY[STRING_SPLIT([a].[TestData], ',') [b];
So for your situation, just a small tweak to what you already have, something like:
SELECT [b].[value] FROM #t a
CROSS APPLY STRING_SPLIT(a.this_column,',') b

Why do I get a 11555 error on this SQL Server inline table valued function?

I am trying to make this function an inline table-valued function on SQL Server 2016.
CREATE FUNCTION ufn_GetBusinessRuleValue
(
-- Add the parameters for the function here
#FieldName VARCHAR(MAX) NOT NULL
)
RETURNS TABLE
AS
RETURN
(
-- Add the SELECT statement with parameter references here
SELECT
FieldValue
FROM
[BVI].[dbo].[BusinessRules] br
WHERE
br.ClientID = DB_NAME()
AND DATEDIFF(DAY, GETDATE(), ActiveDate) <= 0
AND (DATEDIFF(DAY, GETDATE(), InactiveDate) >= 0 OR InactiveDate IS NULL)
AND br.FieldName = 'ufn_GetBVIEmpType.Configuration'
)
When I try to create it with not null parameters I get the following error message:
Msg 11555, Level 15, State 1, Procedure ufn_GetBusinessRuleValue, Line 9 [Batch Start Line 15]
The parameter '#FieldName' has been declared as NOT NULL. NOT NULL parameters are only supported with natively compiled modules, except for inline table-valued functions.
I thought this was an inline table-valued function. Is this not really an inline table-valued function? What am I doing wrong?
You need to remove NOT NULL because it is not supported with inline TVP:
CREATE FUNCTION ufn_GetBusinessRuleValue
(
-- Add the parameters for the function here
#FieldName VARCHAR(MAX)
)
CREATE FUNCTION:
NULL|NOT NULL
Supported only for natively compiled, scalar user-defined functions.

Loading time dimension table t-sql

I am trying to (synthetically) populate an empty time dimension table in a star modeled data mart, after which it should look like this:
I am using the following T-SQL code for this:
/*
STEP 3
Populate DIM_TIJD table with date and its derrived values data
*/
USE Fuzzy_DM_Robin
--DECLARE DATE VARIABLES FOR DATE PERIOD
DECLARE #StartDate datetime = '01/01/1995'
DECLARE #EndDate datetime = '01/01/2026'
DECLARE #DateInProcess datetime
SET #DateInProcess = #StartDate
WHILE #DateInProcess < = #EndDate
BEGIN
SET NOCOUNT ON
--LOOP THROUGH INDIVIDUAL DATES DEFINED BY TIME PERIOD
INSERT INTO DIM_TIJD (
[DATUM_ID],
[DATUM],
[DAG_VD_WEEK],
[WEEKNR],
[MAAND],
[MAAND_OMSCHRIJVING],
[LAATSTE_DAG_MAAND],
[KWARTAAL],
[JAAR]
)
VALUES (
CAST ( #DateInProcess AS numeric (10) ),
#DateInProcess,
CONVERT(varchar(10), #DateInProcess, 110) + ', ' + DATENAME(WEEKDAY, #DateInProcess ),
DATEPART (wk, #DateInProcess),
MONTH( #DateInProcess),
CAST(YEAR(#DateInProcess) as varchar(4)) + ' - ' + DATENAME(MONTH, #DateInProcess ),
DATEPART (dd, EOMONTH ( #DateInProcess)),
DATENAME( QUARTER, #DateInProcess ),
YEAR(#DateInProcess))
END
Nevertheless, it won't load. Messages I receive are:
Message 1:
String or binary data would be truncated
and message 2:
[Execute SQL Task] Error: Executing the query "/*
STEP 3
Populate DIM_TIJD table with date and it..." failed with the following error: "The statement has been terminated.". Possible failure reasons: Problems with the query, "ResultSet" property not set correctly, parameters not set correctly, or connection not established correctly."
What am I doing wrong? There are no under linings in SSMS indicating that something is wrong with the code and I have checked all the varchar lengths to be the same for both the table and the code. I have tried fiddling around with result set settings, but that only gives me another message:
Message 3:
[Execute SQL Task] Error: There is an invalid number of result bindings returned for the ResultSetType: "ResultSetType_SingleRow".
Thank you in advance!
The #DateInProcess variable needs to be incremented as part of the loop.
Try adding this as the last line of your loop (before END):
SET #DateInProcess = DATEADD(DAY, 1, #DateInProcess)

MS SQL Stored Procedure Problem

I have a stored procedure that works fine on my local SQL Server (2005 or 2008 cant recall off hand) but fails when I try to create the procedure on the Production server (SQL 2000).
Any help would be appreciated. TIA.
The stored procedure declaration is this:
/****** Object: StoredProcedure [dbo].[AssignPCSCheckNumbers] Script Date: 06/29/2009 13:12:24 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[AssignPCSCheckNumbers]
(
#MonthEnd DATETIME,
#Seed INT,
#ManifestKey UNIQUEIDENTIFIER,
#Threshold DECIMAL(9,2)
)
AS
SET NOCOUNT ON
BEGIN
--Create a temporary table variable to store our data
DECLARE #MyTemp TABLE
(
ProducerNumber VARCHAR(20),
LastCheckDate DATETIME,
Due DECIMAL(9,2) DEFAULT 0,
Returned DECIMAL(9,2) DEFAULT 0
)
--Fill the table with a listing of producers from our PCSItems table and their ACH Status
INSERT INTO #MyTemp ( ProducerNumber )
SELECT PCSItems.ProducerNumber
FROM PCSItems
LEFT JOIN Producer
ON PCSItems.ProducerNumber = Producer.prodNum
WHERE ISNULL(Producer.PayCommissionByACH,0) = 0
--UPDATE the table with the last time a check was printed for each
--of these producers
UPDATE #MyTemp
SET LastCheckDate = (
SELECT ISNULL(MAX(EntryDate),'1/1/1901')
FROM CommissionLedger WITH (NOLOCK)
WHERE CommissionLedger.TransactionType = 1
AND CommissionLedger.ProducerNumber = [#MyTemp].ProducerNumber
)
--update the table with the amount of comission owed to each producer
UPDATE #MyTemp
SET Due = (
SELECT IsNull(SUM(CommPaid),0)
FROM ProducerComm WITH (NOLOCK)
WHERE ProducerComm.CommApplies = [#MyTemp].ProducerNumber
AND ProducerComm.EntryDate >= LastCheckDate
AND ProducerComm.EntryDate <= #MonthEnd
)
--update the table with the amount of commission returned by each producer
UPDATE #MyTemp
SET Returned = (
SELECT ISNULL(SUM(Amount), 0)
FROM CommissionLedger WITH (NOLOCK)
WHERE CommissionLedger.ProducerNumber = [#MyTemp].ProducerNumber
AND CommissionLedger.EntryDate >= [#MyTemp].LastCheckDate
AND CommissionLedger.EntryDate <= #MonthEnd
)
--create a table to assist with our operations
DECLARE #MyFinal TABLE
(
ID INT IDENTITY(1,1),
ProducerNumber VARCHAR(10)
)
--just insert the producers that are owed an amount over a user specified
--threshold
INSERT INTO #MyFinal ( ProducerNumber )
SELECT ProducerNumber
FROM #MyTemp
WHERE (Due + Returned) > #Threshold
--update our items with the check numbers finally =)
UPDATE PCSItems
SET CheckNumber = (SELECT (([#MyFinal].ID - 1) + #Seed)
FROM #MyFinal
WHERE [#MyFinal].ProducerNumber = PCSItems.ProducerNumber)
SET NOCOUNT OFF
END
GO
And the error the server responds with is this:
Msg 107, Level 16, State 2, Procedure AssignPCSCheckNumbers, Line 35
The column prefix '#MyTemp' does not match with a table name or alias name used in the query.
Msg 107, Level 16, State 2, Procedure AssignPCSCheckNumbers, Line 45
The column prefix '#MyTemp' does not match with a table name or alias name used in the query.
Msg 107, Level 16, State 2, Procedure AssignPCSCheckNumbers, Line 55
The column prefix '#MyTemp' does not match with a table name or alias name used in the query.
Msg 107, Level 16, State 2, Procedure AssignPCSCheckNumbers, Line 55
The column prefix '#MyTemp' does not match with a table name or alias name used in the query.
Msg 107, Level 16, State 2, Procedure AssignPCSCheckNumbers, Line 79
The column prefix '#MyFinal' does not match with a table name or alias name used in the query.
Msg 107, Level 16, State 2, Procedure AssignPCSCheckNumbers, Line 79
The column prefix '#MyFinal' does not match with a table name or alias name used in the query.
That should be created no problem on a 2000 box (and I verified by creating it on my sql 2000 box). Are you sure your database is not in 7.0 compatibility mode?
run
sp_helpdb 'YourDatabaseName'
and look if compatability is 80
I was not aware that 2000 supported table variables, as I suspected in my first answer.
Now I tried in Query Analyzer and found that #table is handled differently from [#table] which results in an error message "invalid object name #table".
I suggest to remove the square brackets from the # table names.
update:
This page indicates using a table alias might fix the problem. I just experimented with:
UPDATE #a SET a = a + b FROM #a INNER JOIN #b ON #a.a = #b.b
which failed with an error. Rewriting as
UPDATE #a SET a = a + b FROM #a aa INNER JOIN #b bb ON aa.a = bb.b
works. Hope it works for you too ;)
This is loosely quoted from a question I asked awhile ago (Link) so if it works for you, upvote Mike L's response instead of mine.
If you use the Database Publishing Wizard to create scripts for your SPs, you can build them in 2005 and use it to deploy to 2000 letting the wizard take care of any compatability issues you may have.
It's not the # notation that is causing the problem, it's the brackets #a not [#a].
It's been a while but I seem to remember SQL 2000 requiring you to use an alias when you are referencing the table in both the update statement and in a subquery. Hope this helps or you find the solution.
AFAIK tables in where clause can't referenced by name and you should their alias for this purpose, in MSSQL2000 book online for search condition we see:
<search_condition>:=
{ constant
| scalar_function
| [ alias. ] column
| local_variable
| ( expression )
| ( scalar_subquery )
| { unary_operator } expression
| expression { binary_operator } expression
}
and as you see, there is no table or alias and it is only alias

Resources