How to convert Persian (shamsi) date to Gregorian in T-SQL? - tsql

I Use A lot data stored in Database to make a report and I was wondering if there is a fast way to convert all of the date in the tables to Persian date when selecting them.
there is some ways to convert but they aren't SQL based and so they are slower than a function just in the SQL.
so if any body knows how to do the converting in the SQL I will thank him a lot.

And a day of searching I decided to do my own style of solving.
and the result is here: Enjoy :D
USE [Test]
GO
/****** Object: UserDefinedFunction [dbo].[MyG2J] Script Date: 10/11/2019 02:35:43 ب.ظ ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[MyG2J](#inputDate DateTime)
RETURNS nvarchar(max)
begin
declare #mDay int,#mMonth int,#mYear int,#sDay int,#sMonth int,#sYear int,#mid int, #isMC bit=0,#isSC bit=0,#preSC bit = 0;
set #mDay=day(#inputDate);
set #mMonth=MONTH(#inputDate);
set #mYear=YEAR(#inputDate);
if #mYear%4=0
set #isMC=1;
else
set #isMC=0;
set #sYear=#mYear-622;
if (#sYear+1)%4=0
set #preSC = 1;
else
set #preSC=0;
select #mid=
case
when #mMonth=1 then'20'
when #mMonth=2 then'19'
when #mMonth=3 then'20'
when #mMonth=4 then'20'
when #mMonth=5 then'21'
when #mMonth=6 then'21'
when #mMonth=7 then'22'
when #mMonth=8 then'22'
when #mMonth=9 then'22'
when #mMonth=10 then'22'
when #mMonth=11 then'21'
when #mMonth=12 then'21'
end
if #isMC=1
begin
set #mid=#mid-1
end
if #mMonth=3 and #mDay=#mid
set #sMonth=#mMonth+9;
else
begin
if (#mMonth=3 and #mDay>#mid) or (#mMonth>3)
begin
set #sYear=#sYear+1;
set #sMonth=#mMonth-3;
end
else
set #sMonth=#mMonth+9;
end
if (#sYear+1)%4=0
set #isSC = 1;
else
set #isSC=0;
if #isMC=1
BEGIN
if #isSC=0
if #mMonth!=3
set #mid=#mid+1
END
else
begin
if #isSC=1
if #mMonth!=3
set #mid=#mid-1
end
if #mDay>#mid
begin
set #sDay=#mDay-#mid;
set #sMonth=#sMonth+1;
end
else
begin
if #sMonth<7
set #sDay=31+(#mDay-#mid);
else
begin
if #sMonth=12
BEGIN
if #isSC=1
set #sDay=30+(#mDay-#mid);
else
set #sDay=29+(#mDay-#mid);
END
else
set #sDay=30+(#mDay-#mid);
end
end
return Cast(#sYear as nvarchar)+'/'+Cast(#sMonth as nvarchar)+'/'+Cast(#sDay as nvarchar)
end

Related

Getting a value from stored procedure within a stored procedure

I have a stored procedure which returns an XML file. At the moment some calculations are done in XSL but I would like to do these within the database using another stored procedure. (adding the result of that calculation to the XML)
ALTER PROCEDURE [dbo].[app_Get_Phone_And_Tariffs]
-- Add the parameters for the stored procedure here
#phone nvarchar(150)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
SELECT
PB.UID as '#phoneid',
PB.Short_Title as '#title',
PB.Description as '#desc',
PB.Camera as '#camera',
PB.Storage as '#storage',
PB.Screen_Size as '#screensize',
PB.OS as '#os',
PB.Processor as '#chip',
PB.Image1 as '#image',
PB.Trade_Price as '#tradeprice',
(SELECT
TB.UID as '#tariffid',
TB.Tariff_Name as '#name',
TB.Carrier as '#network',
TB.Inclusive_Minutes as '#mins',
TB.Inclusive_Texts as '#texts',
TB.Inclusive_Data as '#data',
TB.Monthly_Cost as '#monthly',
TB.Commission as '#comm',
(TB.Commission - PB.Trade_Price) as '#upfront'
FROM dbo.Tariff_Base TB
WHERE TB.Active = 1 AND TB.Type = 1
FOR XML PATH('tariff'), TYPE
),
(SELECT
OP.GP_Margin as '#gpmargin'
FROM dbo.Options OP
FOR XML PATH('options'), TYPE
)
FROM dbo.Phone_Base PB
WHERE PB.Friendly_URL_Name = #phone AND PB.Active = 1
FOR XML PATH('detail'), TYPE
END
What I want to do is:
In the inner select (TB) is to call another SP lets call it "calculate" passing 2 variables (TB.Commission and PB.Trade_Price) for the sum
Calculate will return a value i.e. #hp to the stored procedure which can be added/used in the XML List.
Can this be done in SQL Server 2014/T-SQL?
No. But you could do it with a function. See the MSDN documentation, especially example A.
Something like this (untested):
CREATE FUNCTION dbo.Calculate (#Comission float, #TradePrice float)
RETURNS float
WITH EXECUTE AS CALLER
AS
BEGIN
DECLARE #SumVal float;
SET #SumVal = #Commission + # TradeValue;
RETURN(#SumVal);
END;
GO
--In your sub-query
SELECT values, dbo.Calculate(TB.Commission, PB.Trade_Price) AS A_Sum
FROM ...;

Initialize generator with existing value

I am trying to set a generator with a value that is in some table, I have already seen this question How to set initial generator value? and did what they suggested but I don't know where am I going wrong here.
set term #
execute block
as
declare i int = 0;
begin
i = (select max(some_col) from Table);
gen_id(some_gen,-(gen_id(some_gen,0))); ---set some_gen to 0
gen_id(some_gen,:i); --- set to i
end #
set term ;#
The problem with your code is that you can't execute gen_id in isolation; the parser expects gen_id (or more precisely: a function call) only in a place where you can have a value (eg in a statement or an assignment). You need to assign its return value to a parameter, for example:
set term #;
execute block
as
declare i int = 0;
declare temp int = 0;
begin
i = (select max(id) from items);
temp = gen_id(GEN_ITEMS_ID, -(gen_id(GEN_ITEMS_ID, 0))); ---set some_gen to 0
temp = gen_id(GEN_ITEMS_ID, :i); --- set to i
end #
set term ;#
Please be aware that changing sequences like this is 'risky': if there are any interleaving actions using this same sequence, you might not actually get the result you expected (the sequence might end up at a different value than i and you might get duplicate key errors when another transaction uses the sequence after you subtract the current value (set to 0) and before you add i.
As also noted in the comments, you can also replace your code with:
set term #;
execute block
as
declare i int = 0;
declare temp int = 0;
begin
i = (select max(id) from items);
temp = gen_id(GEN_ITEMS_ID, :i - gen_id(GEN_ITEMS_ID, 0));
end #
set term ;#
Doing it in one statement will reduce the risk of interleaving operations (although it will not remove it entirely).
If you want to use "execute block", you may use something like :
execute block
as
declare i int = 0;
begin
i = (select max(some_col) from some_table);
execute statement ('set generator MY_GENERATOR to ' || :i);
end

Adapt T-SQL code to PL/SQL code

I just have a problem to convert some T-SQL code into PL/SQL.
This is the original part of code :
SET #ISOweek= DATEPART(wk,#DATE)+1
-DATEPART(wk,CAST(DATEPART(yy,#DATE) as CHAR(4))+'0104')
And after many research, i modify like that :
SET #ISOweek = TO_NUMBER(TRUNC(#DATE, 'IW')) + 1
- TO_NUMBER(TRUNC( (TO_CHAR(TRUNC(#DATE, 'YYYY'))) + '0104', 'IW'))
I can't test my code, that's why i come here for obtain your help. Can you say me if it's correct, or not? And what i've to modify because i'm a lost...
I read a lot of articles on this website, always helpfull.
Thank's for your answers
Cordialy,
Guillaume
The first problem it's ok, i've got a lot of responses and thnak's ;).
But i've another problem :
My T-SQL script :
USE [myBD ]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
create function [Entity].[LPAD]
(
#pad_value varchar(500),
#pad_length int,
#pad_with varchar(10) = ' '
)
returns varchar(5000)
as
BEGIN
return ( replace(str(#pad_value,#pad_length),' ',#pad_with) )
END
GO
And i convert it in PL/SQL :
create OR REPLACE FUNCTION myBDOrcl.LPAD
(
pad_value varchar2,
pad_length number,
pad_with varchar2 := ' '
)
return varchar2
is retour varchar2(5000);
BEGIN
retour := replace(TO_CHAR(pad_length, pad_value ), ' ', pad_with);
return retour;
END;
I play the script and it's ok. BUT, i don't know how can I modify my variables : pad_value_varchar2 and the others, to specify the size...
I want to place a declare block, but it's not working....
Thank's for help guys

How to assign variable if Cursor returns Bit of 0

I have written a cursor to search through a table looking at one bit value.
If all values are 1, I send an email. But if one value is 0 in any row, I don't send the email. The issue that I am having comes in my If statement. In SSMS, "#isComplete = 0" is breaking with only an "Incorrect syntax" error. I am not sure what I am missing here. My code is below. Thank you.
-------------------------------------------------
-- Start the INNER Cursor --
-------------------------------------------------
DECLARE #Complete int
DECLARE #isComplete Bit = 1
DECLARE INNERCur CURSOR FOR
SELECT Complete
FROM #AAEAPVS
OPEN INNERCur
FETCH NEXT FROM INNERCur INTO #Complete
WHILE ##FETCH_STATUS = 0
BEGIN
If #Complete = 0
BEGIN
#isComplete = 0
END
FETCH NEXT FROM INNERCur INTO #Complete
END
CLOSE InnerCurs
DEALLOCATE InnerCurs
-------------------------------------------------
-- INNER Curser END --
-------------------------------------------------
The incorrect syntax is that you need to use SET to assign the variable value, so change
#isComplete = 0
to
SET #isComplete = 0
And assuming you want to exit as soon as you find something that is not complete you should change your WHILE condition to
WHILE ##FETCH_STATUS = 0 AND #isComplete = 1
But most important of all, you probably don't need to use a cursor at all - you should avoid cursors in SQL if possible. You can probably just do something like this
DECLARE #isComplete Bit = 1
IF EXISTS (SELECT * FROM #AAEAPVS WHERE Complete = 0)
BEGIN
SET #isComplete = 0
END
and even that is more than you need, you can do it in a single statement
DECLARE #isComplete Bit = 1
SELECT #isComplete = 0 FROM #AAEAPVS WHERE Complete = 0
The syntax error results from not having a statement on the line. You need to use either SET or SELECT to assign a value to a variable, e.g. set #isComplete = 0.
Why, pray tell, a cursor rather than a simple EXISTS query? A far more efficient solution is:
select #isComplete = case
when exists ( select 42 from #AAEAPVS where Complete = 0 ) then 0
else 1 end;
Tip: It is helpful to tag database questions with both the appropriate software (MySQL, Oracle, DB2, ...) and version, e.g. sql-server-2014. Differences in syntax and features often affect the answers.

Pass the Parameter in run time in crystal report 2010

This is my Stored Procedure.
USE [DataStock]
GO
/****** Object: StoredProcedure [dbo].[getBillData] Script Date: 09/19/2014 10:47:21 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[getBillData]
#date1 varchar(20),
#date2 varchar(20)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
SELECT DISTINCT [Billlist].[billno] [Bill No.], temp.[BillDate] [Date], [Billlist].[user] [Customer Name], [Billlist].[total] Total, [paid] Paid, [discount] Discount FROM temp JOIN [Billlist] ON temp.[billno] = [Billlist].[billno] WHERE temp.[BillDate] BETWEEN #date1 and #date2
END
GO
and my crystal report code is,
Report.BillListReport rptBurndown = new Report.BillListReport();
CrystalDecisions.Shared.ConnectionInfo crDbConnection = new CrystalDecisions.Shared.ConnectionInfo();
crDbConnection.IntegratedSecurity = true;
crDbConnection.DatabaseName = "DataStock";
crDbConnection.ServerName = ChangeableFields.ServerName;
CrystalDecisions.CrystalReports.Engine.Database crDatabase = rptBurndown.Database;
CrystalDecisions.Shared.TableLogOnInfo oCrTableLoginInfo;
foreach (CrystalDecisions.CrystalReports.Engine.Table oCrTable in
crDatabase.Tables)
{
oCrTableLoginInfo = oCrTable.LogOnInfo;
oCrTableLoginInfo.ConnectionInfo = crDbConnection;
oCrTable.ApplyLogOnInfo(oCrTableLoginInfo);
}
crystalReportViewer1.ReportSource = rptBurndown;
crystalReportViewer1.RefreshReport();
I don't have idea to parse the parameter in Run Time.
In this code shown another pop up window comes when its running. I need to give that parameters in run time.
Before assigning to report source, call SetParameterValue with name and value for each parameter
rptBurndown.SetParameterValue("ParameterName", value);