Using Date.Now in SQL Function - asp.net

I have a Function like this;
ALTER FUNCTION [dbo].[fngcodeme]
(
#HESAP INT, #DOV INT, #TEKLIF VARCHAR(10), #BAS datetime, #BIT datetime
)
RETURNS FLOAT
AS
BEGIN
DECLARE #Result FLOAT
IF CONVERT(DATETIME, #BIT,103) <= '20110228'
SET #Result = (SELECT SUM(TUTAR)
FROM YAZ..MARDATA.M_HAREKET
WHERE TEMEL_HESAP = #HESAP
AND DOVIZ_KOD = #DOV
AND REF_KOD = 'GC'
AND BACAK_GRUP = 'PERT'
AND ISL_KOD = 1
AND ACIKLAMA LIKE '%' + #TEKLIF + '%'
AND ISL_TAR >= CONVERT(DATETIME, #BAS,103)
AND ISL_TAR <= CONVERT(DATETIME, #BIT,103)
)
ELSE
SET #Result = (SELECT SUM(TUTAR)
FROM YAZ..MARDATA.M_GHAREKET
WHERE TEMEL_HESAP = #HESAP
AND DOVIZ_KOD = #DOV
AND REF_KOD = 'GC'
AND BACAK_GRUP = 'PERT'
AND ISL_KOD = 1
AND ACIKLAMA LIKE '%' + #TEKLIF + '%'
AND ISL_TAR >= CONVERT(DATETIME, #BAS,103)
AND ISL_TAR <= CONVERT(DATETIME, #BIT,103)
)
RETURN #Result
END
M_GHAREKET table is my monthly data table. Every end of the month this table load to M_HAREKET. (And deleted all data in M_GHAREKET)
M_HAREKET is a Big Bucket. M_GHAREKET is small. (I mean M_HAREKET has now over 500.000 data, M_GHAREKET over 4.000)
What i want is for this Function, IF #BAS date's month value is equal DateTime.Now.Month value i want use M_GHAREKET table, else use M_HAREKET table.
How should i change this function like that?
Is it possible like this IF clause with DateTime.Now.Month in SQL Function?
Or i should use in my ASP.NET page? How can i do that?

You can use month and year.
declare #BAS datetime
set #BAS = '2011-03-15'
if month(getdate()) = month(#BAS) and
year(getdate()) = year(#BAS)

You can use DATEDIFF to find the difference between two date in months. This returns the number of time period boundaries crossed so when checking for months it would only return 0 if the two dates are in the same calendar year and month
DECLARE #date1 DATETIME
SET #date1 = '2011-03-01'
SELECT DATEDIFF(MM, #date1, '2011-02-28') -- -1
SELECT DATEDIFF(MM, #date1, '2011-03-20') -- 0
SELECT DATEDIFF(MM, #date1, '2010-03-01') -- -12
So to check that a date is in the same month and year as today (GETDATE()) you could use
DECLARE #date1 DATETIME
SET #date1 = '2011-03-01'
IF DATEDIFF(MM, #date1, GETDATE()) = 0
BEGIN
-- Do your work
END

Related

Change phone number format

I have phone number field in database. It has already data.
I want to change my phone number format to "XXX-XXX-XXXX"
Current database has no any phone format.
So there may be garbage data. I have already applied validation for new records but now I want to change my existing data also.
Is there any specific way through that I can change my existing data. And make all phone numbers to follow this format.
Please advice.
Create function to remove the non-numeric data and do the formatting
CREATE FUNCTION [UDF_STRIP_NONNUMERIC_DATA](#str VARCHAR(8000))
RETURNS VARCHAR(8000)
AS
BEGIN
WHILE Patindex('%[^0-9]%', #str) > 0
BEGIN
SET #str = Stuff(#str, Patindex('%[^0-9]%', #str), 1, '')
END
RETURN #str
END
You can use STUFF function to inset the - between phone number
Select left(Stuff(Stuff(dbo.[UDF_STRIP_NONNUMERIC_DATA](Phone),4,0,'-'),8,0,'-'),12)
From yourtable
If you are using SQL SERVER 2012+ use can use FORMAT function (thanks to LukStorms, who mentioned it in comment)
SELECT Format(Cast(dbo.[Udf_strip_nonnumeric_data](Phone) AS BIGINT), '###-###-####')
FROM yourtable
To update
Update yourtable
SET phone = left(Stuff(Stuff(dbo.[UDF_STRIP_NONNUMERIC_DATA](Phone),4,0,'-'),8,0,'-'),12)
Demo
declare #str varchar(100)= '9225-123-4567'
select left(Stuff(Stuff(dbo.[UDF_STRIP_NONNUMERIC_DATA](#str),4,0,'-'),8,0,'-'),12)
Result : 922-512-3456
declare #phone varchar(24)
set #phone = '(334)789-4532'
--set #phone = '314789-4532'
--set #phone = '3457894532'
--set #phone = '534-789-4532'
SELECT
LEFT(N,3) + '-' + SUBSTRING(N,4,3) + '-' + RIGHT(N,4)
FROM
(SELECT CAST(CAST((
SELECT SUBSTRING(#phone, Number, 1)
FROM master..spt_values
WHERE Type='p' AND Number <= LEN(#phone) AND
SUBSTRING(#phone, Number, 1) LIKE '[0-9]' FOR XML Path(''))
AS xml) AS varchar(MAX)) as N) as N
Ok, to replace all non-numeric characters, look at this.
Here is a sample script (copied from that link) to show you how it works (You'll need to modify this to fit your table name and column names:
-- Step 1: creates table to use to hold every char in every phone number
if object_id('dbo.tally') is not null drop table dbo.tally
select top 10000 --change to fit max length of phone number
identity(int,1,1) as n
into dbo.tally
from master.dbo.syscolumns sc1,
master.dbo.syscolumns sc2
-- add pk to maximize performance
alter table dbo.tally
add constraint pk_tally_n
primary key clustered (n) with fillfactor = 100
-- Step 2: Create temporary table holding three bad phone numbers
declare #phonetable table
(uniqueid int identity(1,1),
phone_number varchar(500))
insert into #phonetable (phone_number)
select '01234-567-890' union
select '012345 6789ext' union
select 'n/a' union select '...12345.....';
-- Step 3: identify, for every character, whether it is a number or not,
and remove the non-numeric ones
with cte (uniqueid, phone_number, goodchar, badchar) as
( select uniqueid, phone_number,
case when substring(phone_number,N,1) not like '%[^0-9]%'
then substring(phone_number,N,1) end as goodchar,
case when substring(phone_number,N,1) like '%[^0-9]%'
then substring(phone_number,N,1) end as badchar
from #phonetable , Tally
where phone_number like '%[^0-9]%' and N <= len(phone_number) )
select distinct phone_number,
isnull( stuff (
( SELECT '' + goodchar
FROM cte t1
where t1.UniqueID = t2.UniqueID
FOR XML PATH ( '' ) ) , 1 , 0 , '' ) ,'')
as clean_phone_number from cte t2
to display the numbers with formatting, just extract the appropriate pieces and re-concatenate them with the dashes.
Select case len(phone)
When 10 then left(phone, 3) + '-' +
substring(phone, 4,3) + '-' +
substring(phone, 7,4)`
When 7 then left(phone, 3) + '-' +
substring(phone, 4,4)
Else '' end
To create a computed column
Alter table Add Column FormattedPhone as
case len(phone)
When 10 then left(phone, 3) + '-' +
substring(phone, 4,3) + '-' +
substring(phone, 7,4)`
When 7 then left(phone, 3) + '-' +
substring(phone, 4,4)
Else '' end
If you don't mind a UDF
Select [dbo].[udf-Str-Format-Phone]('334)789-4532')
Returns
334-789-4532
The UDF
CREATE FUNCTION [dbo].[udf-Str-Format-Phone] (#S varchar(max))
Returns varchar(25)
AS
Begin
Declare #Return varchar(25)
;with cte0(N) As (Select 1 From (Values(1),(1),(1),(1),(1)) N(N))
, cteN(N) As (Select Top (Len(#S)) Row_Number() over (Order By (Select NULL)) From cte0 N1, cte0 N2)
, cteS(S) As (Select Substring(#S,N,1) From cteN Where Substring(#S, N, 1) LIKE '[0-9]' FOR XML Path(''))
Select #Return = IIf(Len(S)>=10,Stuff(stuff(S,4,0,'-'),8,0,'-'),Stuff(S,4,0,'-')) From cteS
Return #Return
End
-- Syntax : Select [dbo].[udf-Str-Format-Phone]('(334)789-4532') -- Returns 334-789-4532
-- Syntax : Select [dbo].[udf-Str-Format-Phone]('Phone:7894532') -- Returns 789-4532

Return 0 if the date for a certain day does not have values

I'm doing a query to return the number of count records for a certain date.
The problem is when I use the GroupBy by a certain day, If the date have no records then the date for that day will not be shown in the output.
How can I achieve that?
I'm doing something like:
SELECT COUNT(History.Id)
FROM History
INNER JOIN User ON User.Id = History.UserId
WHERE (#StartDate = #NullDate OR History.CreatedOnDate >= #StartDate)
AND (#EndDate = #NullDate OR History.CreatedOnDate <= #EndDate)
GROUP BY History.CreatedOnDat
Example
01-08, 3 records
02-08, 2 records
04-08, 5 records
I need to have 03-08 with 0 records.
Create a temp table with one day per row:
Declare #StartDate datetime = '2016-08-01'
Declare #EndDate datetime = '2016-08-31'
declare #temp table
(
oneday datetime
);
WHILE #StartDate <= #EndDate
begin
INSERT INTO #temp VALUES (#StartDate);
SET #StartDate = Dateadd(Day,1, #StartDate);
end
select * from #temp
Then, simply join your query with this temp table.

How to Get Month Text In Arabic?

I have This below query its working fine for Month Text in English but we need Month Text in Arabic How we do??I have Sql Server 2008R2.I have check using FORMAT function but its not work in 2008r2 edition.
DECLARE #tempdate TABLE
(
pricedate DATETIME NOT NULL,
priceid INT NOT NULL
)
INSERT INTO #tempdate
(pricedate,
priceid)
SELECT pricelist_date,
pricelist_id
FROM vw_lu_region_and_date_list
WHERE price_status = '3'
AND region_id = '1'
AND saletype = '2'
ORDER BY pricelist_date DESC;
WITH numbered
AS (SELECT *,
Row_number()
OVER (
partition BY Dateadd(month, Datediff(month, 0, pricedate), 0
)
ORDER BY pricedate DESC) AS rn
FROM #tempdate)
SELECT RIGHT(CONVERT(NVARCHAR(20), pricedate, 106), 8) AS PRICELIST_DATE,
priceid AS PRICELIST_ID
FROM numbered
WHERE rn = 1
ORDER BY priceid DESC
I have get result from above query like
Apr 2013
Mar 2013
but we need like Apr and Mar in Arabic????
I also suggest to store as normal date and you can probably convert in your client application rather than in SQL.
In the organization I once worked for the previous developer designed a SQL CLR function to convert dates into Hebrew dates and return in Hebrew.
But You Can Use This :
CREATE FUNCTION dbo.fnTranslateMonthNameToArabic
(#date as datetime)
RETURNS nvarchar(50)
AS
BEGIN
DECLARE #result AS nvarchar(50);
IF MONTH(#date) = 1
SET #result = (SELECT CONVERT(nvarchar(2), DAY(#date)) + N' ' + N'يناير' + N' ' + CONVERT(nvarchar(4), YEAR(#date)));
IF MONTH(#date) = 2
SET #result = N'and so on ...';
RETURN #result;
END
Go
-- Test
SELECT dbo.fnTranslateMonthNameToArabic({d N'2012-01-16'}) AS Arabic
At Last Please Take a Look at Arabic Language Support in SQL Server

Condensing several SQL queries into a single query so a parameter can be used for different data types

I'm looking to Condense several SQL Server queries into a single query so a parameter can be used for different data types. These types are dates, or numbers or strings. The parameter is called: #SearchValue.
In a strongly typed DataSet we have the 3 queries listed below.
This is for ASP.Net with a VB.Net code-behind file but I think this question is may also be good for non ASP.Net as well.
I call this one if the user enters a date into a search TextBox:
Query:
SELECT ID, PaymentAmount, PaymentDate, WhatWasPaymentFor
FROM Payments
WHERE (ParentID = #ParentID) AND
(PaymentDate = #SearchValue)
Call from VB.Net code-behind for the date search query:
tblObject = theTableAdapter.GetDataByPaymentDate(dcmParentsId, TextBoxSearch.Text)
If tblObject.Count() > 0 Then
GridViewSummary.DataSource = tblObject
GridViewSummary.DataBind()
End If
The other ones are for numbers only and the last one is for everything else.
This one is for numbers only:
SELECT PaymentDate, PaymentAmount, WhatWasPaymentFor, ID
FROM Payments
WHERE (ParentID = #ParentID) AND
(PaymentAmount = #SearchValue)
This one is called when the other 2 queries don't find any data:
SELECT PaymentDate, PaymentAmount, WhatWasPaymentFor, ID
FROM Payments
WHERE (ParentID = #ParentID) AND
((WhatWasPaymentFor LIKE '%' + #SearchValue + '%') OR
(#SearchValue = 'ALL'))
All of this coding works as is and I did it this way because there would be an error if I tried to call .GetDataByPaymentDate with a non date value.
Is there a way to use a single query to handle the searching by dates, numbers, and strings?
* UPDATES *
Thanks for all the sample queries. I am trying all of the sample queries in the SQL Server Management Studio to see what results come up.
I this one based on Gordon's query but it does not return any data:
DECLARE #SearchValue VARCHAR = '01/01/2012'
DECLARE #SearchType VARCHAR = 'Dates'
DECLARE #ParentID INT = 3
SELECT ID, PaymentAmount, PaymentDate, WhatWasPaymentFor
FROM Payments cross join
(select #SearchValue as sv) const
WHERE ParentID = #ParentID AND
(case when #SearchType = 'Dates' and ISDATE(const.sv) = 1
then (case when PaymentDate = CAST(const.sv AS datetime) then 'true' else 'false' end)
when #SearchType = 'Numbers' and ISNUMERIC(const.sv) = 1
then (case when PaymentAmount = cast(const.sv as Int) then 'true' else 'false' end)
when #SearchType = 'Everything Else'
then (case when WhatWasPaymentFor LIKE '%' + const.sv + '%' OR const.sv='ALL' then 'true' else 'false' end)
end) = 'true'
This is based on the one from gh9 and pulls up data. Thanks gh9:
DECLARE #SearchValue VARCHAR = 'Books'
DECLARE #ParentID INT = 3
DECLARE #PaymentDate DATETIME = NULL
DECLARE #PaymentAmount MONEY = NULL
SELECT ID, PaymentAmount, PaymentDate, WhatWasPaymentFor
FROM Payments
WHERE ParentID = #ParentID
AND (#paymentDate is null OR PaymentDate = #Paymentdate)
AND (#paymentAmount is null OR paymentAmount = #paymentAmount)
AND ((#SearchValue is null OR
(WhatWasPaymentFor LIKE '%' + #SearchValue + '%' OR #SearchValue='ALL'))
)
This lets you take advantage of not having to cast searchvalue to whatever you need, also is a bit more readable. Modify the syntax as needed, but the key idea is to use sql server ability to have null parameters and short circuit logic to evaluate strongly typed parameters instead of casting to the data type you need.
#ParentID INT
#PaymentAmount INT = NULL
#PaymentDate Datetime = null
#GenericSearchTerm varchar(100) = null
AS
BEGIN
SELECT
ID,
PaymentAmount,
PaymentDate,
WhatWasPaymentFor
FROM Payments
WHERE #ParentID = #ParentID
AND ( (#paymentDate is null OR PaymentDate = #Paymentdate))
AND (#paymentAmount is null OR paymentAmount = #paymentAmount))
AND ( #GenericSearchTerm is null OR ((WhatWasPaymentFor LIKE '%' + #GenericSearchTerm + '%' OR #SearchValue='ALL'))
EDIT:updated answer per #andriyM comments
How about adding a third parameter of #SearchType with possible values of ('datetime','int', or 'nvarchar') and using it in your WHERE clause to cast the #SearchValue to appropriate type for comparison. Something like:
SELECT
ID,
PaymentAmount,
PaymentDate,
WhatWasPaymentFor
FROM Payments
WHERE #ParentID = #ParentID
AND (
(#SearchType = 'datetime' AND PaymentDate = CAST(#SearchValue AS datetime))
OR
(#SearchType = 'int' AND PaymentAount = CAST(#SearchValue AS int))
OR
(#SearchType = 'nvarchar' AND
(WhatWasPaymentFor LIKE '%' + #SearchValue + '%' OR #SearchValue='ALL')
);
This is inspired by Bstateham's answer, but it does two things differently. First, it stores the values in a table, turning them from constants into variables. Second, it uses the case because that guarantees shortcircuiting.
This results in something like:
SELECT ID, PaymentAmount, PaymentDate, WhatWasPaymentFor
FROM Payments cross join
(select #SearchValue as sv) const
WHERE #ParentID = #ParentID AND
(case when #SearchType = 'datetime' and ISDATE(const.sv) = 1
then (case when PaymentDate = CAST(const.sv AS datetime) then 'true' else 'false' end)
when #SearchType = 'int' and ISNUMERIC(const.sv) = 1
then (case when PaumentAmount = cast(const.sv as Int) then 'true' else 'false' end)
when #SearchType = 'nvarchar'
then (case when WhatWasPaymentFor LIKE '%' + const.sv + '%' OR const.sv='ALL' then 'true' else 'false' end)
end) = 'true'
I also added in validation checks for the conversion to integer and date (not perfect, but will help). Also, you should probably name the #SearchType after the destination field rather than the type. However, I've kept the version with the type name.

Stored Procedure Where Clause Parameters

I've got an ASP.net search page where the user can enter one or more search criteria. The page calls a stored procedure to query a MS SQL Server 2008 db.
Part of the search criteria is single date or date range. If the user supplies Date1, we search on a single date. If the user supplies Date1 and Date2, we search on a date range.
My issue is coding this logic in the stored proc.
#Date1 datetime
#Date2 datetime
..other search params...
So there are three conditions:
Both #Date1 and #Date2 are null (the user is not searching on dates)
#Date1 is not null and #Date2 is null (the user is searching on a single date)
#Date1 is not null and #Date2 is not null (user is searching a date range)
I can't figure out how to structure the WHERE clause to handle each of the three possible conditions.
I'm familiar with ISNULL() and COALESCE()
Any tips or suggestions are greatly appreciated.
CREATE PROCEDURE BLABLABLA(
#DATE1 DATETIME = NULL,
#DATE2 DATETIME = NULL
)
AS
BEGIN
SELECT COL1, COL2
FROM THE_TABLE
WHERE
THE_TABLE.DATETIMEFIELD BETWEEN
ISNULL(#DATE1, THE_TABLE.DATETIMEFIELD)
AND COALESCE(#DATE2, #DATE1, THE_TABLE.DATETIMEFIELD)
END
Another choice, losing some expressiveness but likely using indexes, could be:
CREATE PROCEDURE BLABLABLA(
#DATE1 DATETIME = NULL,
#DATE2 DATETIME = NULL
)
AS
BEGIN
SELECT COL1, COL2
FROM THE_TABLE
WHERE
(THE_TABLE.DATETIMEFIELD >= #DATE1 OR #DATE1 IS NULL)
AND (THE_TABLE.DATETIMEFIELD <= #DATE2
OR THE_TABLE.DATETIMEFIELD = #DATE1
OR (#DATE1 IS NULL AND #DATE2 IS NULL))
END
You could try to create your SQL query as a string in the SP and then execute it, like this:
...
declare #sql varchar(500)
set #sql = 'select from myTable where 1=1'
if(#Date1 <> null)
set #sql = #sql + ' and date1 >= '+ #date1
if(#Date2 <> null)
set #sql = #sql + ' and date2 <= '+ #date2
print(#sql) -- for debug
exec(#sql)

Resources