Date problems inserting data using stored procedures - sql

I have a table in my SQL Server database with a field DateAdded. I only want the date and time as the format dd/mm/yyyy hh:mm:ss so I have the smalldatetime data type selected for this field. I'm now creating a stored procedure to insert data into this table. Amongst other fields - not relevant to question - is the DateAdded as this is a non NULLABLE field.
My procedure is as follows:
alter procedure dbo.spAddStuffExample_Insert
#Name varchar(100),
#EmailAddress varchar(100),
#ContactNumber varchar(100),
#AdditionalInformation varchar(3000) = NULL,
#DateAdded smalldatetime = GetDate
as
begin
set nocount on;
insert into dbo.TableName (Name, EmailAddress, ContactNumber,AdditionalInformation , DateAdded)
values(#Name, #EmailAddress, #ContactNumber,#AdditionalInformation, #DateAdded)
end
The wrong date is added to the record. DateAdded is 1900-01-01 00:00:00. I don't care about the format but it certainly isn't the 1900s.

The only things you can pass to a stored procedure are constants and variables.
Per Microsoft Reference: https://learn.microsoft.com/en-us/sql/relational-databases/stored-procedures/specify-parameters?view=sql-server-ver16
GETDATE() is a function and functions cannot be used to pass parameter values or used as the default parameter values. You have to remove the default value using the GETDATE() function.
Two possible workarounds to your problem.
Declare a local variable inside the stored procedure set to GETDATE(). Use that local variable.
Create a variable set to GETDATE(), and pass the variable to the stored procedure.
Ex of #1 above, declaring a local variable inside the stored procedure:
CREATE PROCEDURE dbo.spAddStuffExample
--These are Passed Parameters, these cannot use functions
#Name varchar(100),
#EmailAddress varchar(100),
#ContactNumber varchar(100),
#AdditionalInformation varchar(3000) = NULL -- = NULL is a default
AS
--Declare local variable using a function
DECLARE #DateAdded smalldatetime = GETDATE();
set nocount on;
--Use passed parameters and local variable together
insert into dbo.TableName (Name, EmailAddress, ContactNumber,AdditionalInformation , DateAdded)
values(#Name, #EmailAddress, #ContactNumber,#AdditionalInformation, #DateAdded);

Related

SQL Stored Procedure Parameters Being Assigned to Variables

I'm sure there is some sound logic/best practice but I'd like it explained to me if possible. Looking at SQL stored procedures written by a previous employee he always declares 1 variable for each parameter and sets the variable equal to the parameter value and then uses the variable throughout the remainder of the stored procedure. What is the added value in not just using the parameter vs assigning to a variable?
ALTER procedure [dbo].[sp_shipping]
(
#p_date varchar(10),
#p_status varchar(10),
#p_cust nvarchar(20)
)
as
set nocount on
declare #v_date datetime,
#v_status varchar(10),
#v_cust nvarchar(20)
select #v_date = convert(datetime,#p_date),
#v_status = #p_status,
#v_cust = #p_cust
It is likely just a preference/style but it is worth noting that it does have an impact on the #p_date variable,
select #v_date = convert(datetime,#p_date)
This will throw an error if it is unable to convert the parameter to a datetime and it stores the result of the conversion so you don't have to repeat it later in the stored procedure.

"Must declare the scalar variable" error when executing a stored procedure

I have tried to make a procedure to insert a price:
create procedure prInsertPrice
#NuggetID varchar(5),
#Unit_Price money,
#Start_Date datetime,
#End_Date datetime
as
begin
DECLARE #date AS DATETIME
SET #date = GETDATE()
if
(
(#NuggetID like 'N[0-9][0-9]')
and
(#Unit_Price is not null)
and
(#Start_Date is not null)
)
begin
print 'Insert Success'
insert NuggetPrice (NuggetId, Unit_Price, Start_Date, End_Date)
values (#NuggetID, #Unit_Price, #Start_Date, #End_Date)
end
else
begin
print 'Failed to insert'
end
end
When I execute the procedure it's fine, but when I run the procedure like this:
EXEC prInsertPrice 'N01', 20000, #date, null
I get the error message:
Must declare the scalar variable #date.
Why is this and how can I correct the problem?
The #date in the exec statement is different then the one in the stored proc.
You should do something like:
DECLARE #date AS DATETIME
SET #date = GETDATE()
EXEC prInsertPrice 'N01', 20000, #date, null
When you run:
EXEC prInsertPrice 'N01', 20000, #date, null
You are passing the variable #date as the third parameter to your stored procedure, as #Start_Date. This is entirely separate from the #date variable which you have declared inside the stored procedure itself, which gets declared and initialised after the procedure has been called, as it executes.
If you have not initialised the #date variable which is being passed as a parameter to the stored procedure before calling the stored procedure, then you will get the error you have described.
So, you need to declare and initialise this variable first:
DECLARE #date DATETIME = '2017-01-01' -- You can whatever date value you require here
EXEC prInsertPrice 'N01', 20000, #date, null
This should prevent the error.
Note: You can also separate the declaration and initialisation of the #date variable if you would prefer:
DECLARE #date DATETIME
SET #date = '2017-01-01'
In addressing your underlying problem though or preventing bad data being inserted into your NuggetPrice table though, I would agree with Prdp's suggestion of adding a CHECK Constraint to the table, for example:
ALTER TABLE NuggetPrice
ADD CONSTRAINT CK_NuggetPrice CHECK (NuggetID LIKE 'N[0-9][0-9]'
AND Unit_Price IS NOT NULL
AND Start_Date IS NOT NULL)
This would also prevent anyone from inserting records which do not agree with the logic specified.
Already other two answers gave enough information on the reason for error so am not going to talk about it. Here is different approach to solve the data validation
Instead of creating a Stored Procedure to restrict inserting bad data into table, I would suggest you to create a Check constraint to do this
ALTER TABLE NuggetPrice
ADD CONSTRAINT CK_NuggetPrice CHECK (NuggetID LIKE 'N[0-9][0-9]' AND Unit_Price IS NOT NULL AND Start_Date IS NOT NULL)
This will make sure nobody inserts bad data in NuggetPrice

SQL. Trying to create a stored procedure on SQL, but not sure if I have the right query

Create a SQL stored procedure that parses a string into previously unknown number of fields. The inputs would be
a text string of undetermined length;
a delimiter, passed as a string;
a nullable column that, if relevant, would pass the text indicator as a single character string.
The resulting table would be entirely dependent on the string used as an input
Please help because I cannot figure this out. I know this is wrong, but I had no clue where to begin.
Here is what I have tried so far:
DECLARE #l INT, #c VARCHAR(MAX) = ''
SELECT #l = MAX(LEN(n)) FROM AdventureWOrk
DECLARE #s NVARCHAR(MAX) = '
;WITH cte AS
)
Insert INTO #Values (1, 'CGID', 'EENumber', 'EEYID', 'SSN' )
SELECT
[Value],
[Value],
Prod_Attributes.value('/Attribute[1]','varchar(MAX)') AS [CGID],
Prod_Attributes.value('/Attribute[2]','varchar(MAX)') AS [EENUMBER],
Prod_Attributes.value('/Attribute[3]','varchar(MAX') AS [EYEID],
Prod_Attributes.value('/Attribute[4]','varchar(MAX') AS [SSN]
You can create a stored procedure by using the following syntax:
CREATE PROCEDURE usp_YourProcedure
AS
BEGIN
-- Your logic
END
You would put the code you already have within the BEGIN statement.
To execute the stored procedure you can do:
EXEC usp_YourProcedure
To add parameters, simply state them after the CREATE PROCEDURE declaration.
CREATE PROCEDURE usp_YourProcedure
(
#TextField VARCHAR(MAX),
#Delimeter VARCHAR(1),
#TextIndicator CHAR(1) = NULL
)
AS
BEGIN
END
Then to execute with parameters:
EXEC usp_YourProcedure 'String literal, with commas, which will, be stripped out by the delimiter', ','
Further details are outlined at MSDN.
As an additional note, try keeping your variable names descriptive and consistent, also check the casing.
CREATE PROCEDURE <ProcedureName>
-- Add the parameters for the stored procedure here
<Param1>, <Param2> ...
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
END
GO

How to pass more than one values as parameter to sql statement?

I have one big SQL query and I want to pull out some data using that query
declare #Period VARCHAR(10) = 'MTD'
declare #Date DATETIME = '2011-08-31'
and I have a big select statement where I'm passing above parameters and it executes the output.
Now I have 10 different dates which I need to pass here each time to see the result.
How can I pass those date to above parameter declare #Date DATETIME how can I hard code it ?
So my desired output will be for those selected dates, give me hint for at least 3 dates ?
Use a table-valued parameter. First, create a type:
CREATE TYPE dbo.Dates AS TABLE(d DATE);
Now your stored procedure can take this type as a parameter:
CREATE PROCEDURE dbo.whatever
#d dbo.Dates READONLY
AS
BEGIN
SET NOCOUNT ON;
SELECT t.columns
FROM dbo.tableName AS t
INNER JOIN #d AS d
ON t.[date] = d.d;
END
GO
Then from your application you can pass this parameter in as a DataTable, for example.

change-data-capture from many tables via a single stored procedure?

I need to retrieve change-data-capture rows for several tables, and I'm required (by company IT policy) to access the database via stored procedures. I would rather create a single stored procedure with the table name as a parameter, rather than one stored procedure for each table I'm monitoring. Where I get hung up is that CDC defines a separate table-valued function name for each table monitored, and I'm not sure how best to generalize around that.
Is it possible to modify the following example code so that it invokes cdc.fn_cdc_get_net_changes_dbo_ + #Table instead of cdc.fn_cdc_get_net_changes_dbo_TABLE ?
Is there another approach I should use?
create proc [dbo].GetChangesForTable
#Table varchar(50),
#BeginTime datetime,
#EndTime datetime
as
begin
DECLARE #begin_lsn binary(10), #end_lsn binary(10);
DECLARE #func nvarchar(128)
if #EndTime is null select #EndTime=GETDATE()
SELECT #begin_lsn = sys.fn_cdc_map_time_to_lsn('smallest greater than', #BeginTime);
SELECT #end_lsn = sys.fn_cdc_map_time_to_lsn('largest less than or equal', #EndTime);
-- HOW TO GET THE CORRECT FUNCTION CALLED HERE?
SELECT * FROM cdc.fn_cdc_get_net_changes_dbo_TABLE(#begin_lsn, #end_lsn, 'all')
end
GO
I think that's possible with sp_executesql like that :
DECLARE #sql nvarchar(4000)
SET #sql = N'SELECT * FROM cdc.fn_cdc_get_net_changes_dbo_'+cast(#TABLE as varchar)+'(#begin_lsn, #end_lsn, 'all')'
EXEC sp_executesql #sql, N'#Table varchar(50), #BeginTime datetime, #EndTime datetime',#Table,#BeginTime,#EndTime