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
Related
I would like to utilize the Month Column in the below syntax in a Case Statement. When I create a sub query I receive the Oracle error 01788 Connect By Clause Required in query block. How can one utilize the Month column in the case statment in the subquery?
TO_CHAR(ADD_MONTHS(TRUNC(StartDate, 'MM'), LEVEL - 1), 'YYYYMM') AS Month
Query below:
SELECT
CASE
WHEN first_assgn_dt_YYYYMM <= Month
THEN 0
WHEN EndDate < LAST_DAY(EndDate) AND EndDate != sysdate
AND LEVEL = 1 + MONTHS_BETWEEN(TRUNC(EndDate,'MM'),TRUNC(StartDate,'MM'))
THEN 0
ELSE 1
END AS active_at_month_end
FROM (
WITH
ActiveMemberData (ID,StartDate,EndDate,first_assgn_dt,first_assgn_dt_YYYYMM) AS (
SELECT DISTINCT
x.ID,
TRUNC(x.start_dt) AS StartDate,
CASE WHEN TRUNC(X.END_DT) = '1-JAN-3000' THEN SYSDATE ELSE TO_DATE(X.END_DT) END AS EndDate,
x.first_assgn_dt,
TO_CHAR(first_assgn_dt,'YYYYMM') AS first_assgn_dt_YYYYMM
FROM X
LEFT JOIN D ON X.MID = D.ID
WHERE 1=1
)
--------------------------------------------------
SELECT DISTINCT
ID,
first_assgn_dt,
first_assgn_dt_YYYYMM,
StartDate,
TO_CHAR(StartDate,'YYYYMM') AS StartDate_YYYYMM,
EndDate,
TO_CHAR(ADD_MONTHS(TRUNC(StartDate, 'MM'), LEVEL - 1), 'YYYYMM') AS Month,
LAST_DAY(EndDate) AS LastDayOfMonth
FROM ActiveMemberData
WHERE 1=1
------------------------------------------------------------------------------------
CONNECT BY LEVEL <= 1 + MONTHS_BETWEEN(TRUNC(EndDate,'MM'), TRUNC(StartDate,'MM'))
AND PRIOR ID = ID AND PRIOR STARTDATE = STARTDATE
AND PRIOR sys_guid() IS NOT NULL
) Z
WHERE 1=1
ORDER BY
ID,
Month
That has nothing to do with trying to refer to Month from the inline view; that is fine. It's the separate reference to level that is causing the error.
If you want to be able to see the level from your inline view in the outer query, as you are with this line:
AND LEVEL = 1 + MONTHS_BETWEEN(TRUNC(EndDate,'MM'),TRUNC(StartDate,'MM'))
then you have to include it in the select list - with an alias - and then refer to that alias:
SELECT
CASE
...
AND LEVEL_ALIAS = 1 + MONTHS_BETWEEN(TRUNC(EndDate,'MM'),TRUNC(StartDate,'MM'))
...
FROM (
...
SELECT DISTINCT
LEVEL as LEVEL_ALIAS,
ID,
...
You can call the alias whatever you want, of course; you just can't use the reserved word level.
Anything you want visible in the outer query always has to be in the inline view's select list - but usually you can keep the original column name; you have to use an alias for an expression or a pseucocolumn though, which is the case here.
You don't have to use an alias for the reserved word. Just add double quotes and capitilise it i.e. "LEVEL"
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
I am doing a long to string conversion using java in following way.
Long longValue = 367L;
String str = Long.toString(longValue, 36).toUpperCase();
this is returning me as value A7. how can achieve this in doing oracle sql.
UPDATED:
Hi, I have analyzed how java code is working then wanted to implement the same thing in procedure.
First point is Input vaues. LONG and Radix. in my case Radix is 36. so i will have values from 1..9A...Z0 It picks up the values from this set only.
Second point Long value as input. we have to divide this value with radix. if the quotient is more than 36 again we need to divide.
For eaxmple 367 then my converted value is 10(quotient) 7(remainder) that is A7.
3672 converted value is 102 0 i need to do again for 102 that is 2 -6 so my final value will be 2-6 0 that is 2U0(- means reverse the order).
UPDATE 2:
Using oracle built in functions we can do this. this was solved by my friend and gave me a function.I want to thank my friend. this will give me an out put as follows.
367 then my converted value is 10(quotient) 7(remainder) that is *A*7.(I modified this to my requirement).
FUNCTION ENCODE_STRING(BASE_STRING IN VARCHAR2,
FROM_BASE IN NUMBER,
TO_BASE IN NUMBER)
RETURN VARCHAR2
IS
V_ENCODED_STRING VARCHAR(100);
BEGIN
WITH N1 AS (
SELECT SUM((CASE
WHEN C BETWEEN '0' AND '9'
THEN TO_NUMBER(C)
ELSE
ASCII(C) - ASCII('A') + 10
END) * POWER(FROM_BASE, LEN - RN)
) AS THE_NUM
FROM (SELECT SUBSTR(BASE_STRING, ROWNUM, 1) C, LENGTH(BASE_STRING) LEN, ROWNUM RN
FROM DUAL
CONNECT BY ROWNUM <= LENGTH(BASE_STRING))
),
N2 AS (
SELECT (CASE
WHEN N < 10
THEN TO_CHAR(N)
ELSE CHR(ASCII('A') + N - 10)
END) AS DIGI, RN
FROM (SELECT MOD(TRUNC(THE_NUM/POWER(TO_BASE, ROWNUM - 1)), TO_BASE) N, ROWNUM RN
FROM N1
CONNECT BY ROWNUM <= TRUNC(LOG(TO_BASE, THE_NUM)) + 1)
)
SELECT SYS_CONNECT_BY_PATH(DIGI, '*') INTO V_ENCODED_STRING
FROM N2
WHERE RN = 1
START WITH RN = (SELECT MAX(RN) FROM N2)
CONNECT BY RN = PRIOR RN - 1;
RETURN V_ENCODED_STRING;
IN PL/SQL (or Oracle SQL) you have the a function called TO_CHAR.
http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions181.htm
It is not possible to do it in the pure SQL. You have to use PL/SQL.
Simple example how to do it PL/SQL:
CREATE TABLE long_tbl
(
long_col LONG
);
INSERT INTO long_tbl VALUES('How to convert the Long value to String using sql');
DECLARE
l_varchar VARCHAR2(32767);
BEGIN
SELECT long_col
INTO l_varchar
FROM long_tbl;
DBMS_OUTPUT.PUT_LINE(l_varchar);
END;
-- How to convert the Long value to String using sql
There is TO_LOB function but it can only by used when you insert data into table.
http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions185.htm
You can apply this function only to a LONG or LONG RAW column, and
only in the select list of a subquery in an INSERT statement.
There is also other, more proper way to do it by using "dbms_sql.column_value_long" but this gets complicated (fetching of the LONG column and appending to the CLOB type.)
http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_sql.htm#i1025399
(Oracle Database PL/SQL Packages and Types Reference)
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.
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