How to retrieve value from SQL server DB? - sql-server

The following query works fine:
select ProductNumber,Name,Color,ListPrice
from Production.Product
where ProductNumber = 'AR-5381'
Where as when,
I'm writing my code like following to retrieve value from SQL sever:
declare #ProductNum nvarchar
set #ProductNum = 'AR-5381'
select ProductNumber,Name,Color,ListPrice
from Production.Product
where ProductNumber = #ProductNum
I'm not able to get the values. But ProductNumber('AR-5381') is present in the table.
What I'm doing wrong?

Variable is declared with default length which is 1.
nvarchar without specifying length means nvarchar(1)
so following nvarchar varaible only store first character in the string because its length is one.
declare #ProductNum nvarchar
set #ProductNum = 'AR-5381'
SELECT #ProductNum
Output
A
declare #ProductNum nvarchar(2)
set #ProductNum = 'AR-5381'
SELECT #ProductNum
Output
AR
You should specify some length like.
declare #ProductNum nvarchar(255)
set #ProductNum = 'AR-5381'
select ProductNumber,Name,Color,ListPrice
from Production.Product
where ProductNumber =#ProductNum

Related

SSRS Multi-Select and For-Each Stored-Procs

I am using an SSRS multi-select which gives me an unknown number of values > 0. That is something like the following (1),(4),...(x).
I want to union the results of a stored procedure for each ID that SQL receives.
If this came as a table my job would be easier.
ID
1
4
...
x
I found the following code got me a good way there:
DECLARE #MyTempTable TABLE (txtType NVARCHAR(20), intID integer, txtAccountCode NVARCHAR(50), txtSchoolID NVARCHAR(50), txtSageCode NVARCHAR(50), ChargeCode NVARCHAR(50),
txtDescription NVARCHAR(200), mAmount DECIMAL(18,2), percentageAmount DECIMAL(18,2), txtChargeType NVARCHAR(50), txtNominalAccount NVARCHAR(50), bBilledInAdvance BIT)
DECLARE #i int
DECLARE #CycleId int
DECLARE #numrows int
DECLARE #Cycle Table (
idx smallint IDENTITY(1,1)
, CycleId int
)
INSERT #Cycle (CycleId)
SELECT [TblFeeBillingCycleID] FROM [TblFeeBillingCycle] WHERE [TblFeeBillingCycleID] IN(#intCycleId)
SET #i = 1
SET #numrows = (SELECT COUNT(*) FROM #Cycle)
IF #numrows > 0
WHILE (#i <= (SELECT MAX(idx) FROM #Cycle))
BEGIN
SET #CycleId = (SELECT CycleId FROM #Cycle WHERE idx = #i)
INSERT INTO #MyTempTable
EXEC usp_cust_GetTransactionsByCycle #CycleId
SET #i = #i + 1
SET #i = #i + 1
END
If I could either unpivot my row of unknown length and unknown columns then this would work I think.
I also thought there was a way to insert into a table by wrapping values, so it chops a long row of data into x rows matching the length of the new table.
Then again there may be another way to iterate up a table of unknown length and unknown columns names.
SQL might be the wrong way to go, I just fear SSRS is pushing me in this direction, I don't know if I can do the foreach in SSRS instead.
If the question is about how to transform string into table then yuo can use STRING_SPLIT
DECLARE #InString VARCHAR(20);
SET #InString='1,2,3,4,5,6,7,8,9,10';
SELECT VALUE FROM string_split(#InString,',');
I think it's a kind of madness but I found a workaround to get a table of values from the results from SSRS. I query the IDs against a source table using IN().
SELECT [TblFeeBillingCycleID]
FROM [TblFeeBillingCycle]
WHERE [TblFeeBillingCycleID] IN(#intCycleId)

How to get the abbreviation of a word in TSQL?

For example, if I have an input string "OrderTrackingNumber", I want it to return "OTN". Or if I have an input string "MyOrder", I want it to return MO.
Providing your column names are always camel cased with the first letter capitalised, you can use the following:
create function fn_extractupper(#var varchar(50))
returns varchar(50)
as
begin
declare #aux varchar(50) = ''
declare #size int = len(#var)
declare #position int = 0
while #position < #size
begin
if ASCII(SUBSTRING(#var,#position,1)) = ASCII(UPPER(SUBSTRING(#var,#position,1)))
begin
set #aux = #aux + SUBSTRING(#var,#position,1)
end
set #position = #position + 1
end
return #aux
END
Starting with SQL Server 2017 you should read about the new function TRANSLATE. Together with a case sensitive collation this should be good for your issue.
But most people don't have this version (me too). So you might try this:
DECLARE #mockupTable TABLE(ID INT IDENTITY, InputString VARCHAR(100));
INSERT INTO #mockupTable VALUES('OrderTrackingNumber')
,('MyOrder')
,('OneMoreExample');
WITH recCTE AS
(
SELECT ID
,InputString
,2 AS NextPos
,SUBSTRING(InputString,1,1) AS Letter
FROM #mockupTable AS mt
UNION ALL
SELECT r.ID
,r.InputString
,r.NextPos+1
,SUBSTRING(r.InputString,r.NextPos,1)
FROM recCTE AS r
WHERE r.NextPos<LEN(r.InputString)+1
)
SELECT r1.ID
,(
SELECT r2.Letter AS [*]
FROM recCTE AS r2
WHERE ASCII(r2.Letter) BETWEEN ASCII('A') AND ASCII('Z')
AND r1.ID=r2.ID
FOR XML PATH('')
)
FROM recCTE AS r1
GROUP BY r1.ID
The recursive CTE will walk along the letters and return them one by one.
The final query uses a grouping query outside and a sub-select, returned as XML.
This will be the re-concatenated string.
Without the inner WHERE checking for the ASCII() values the result would be exactly the same as the initial values.

Create a table in SQL Server from a tables values

Ok, Stay with me here and lets see if anyone knows if this can be done.
I initially query a table to bring back just 1 row, this row has the data that I will use.
What I need to do is, convert that 1 row to a table where each column value is aligned with what the column name was.
So I query a table to get 1 row, say a table called colours and in it there are the columns Name, Hue, Populatiry.
I need to get that 1 row to be a table where the values of lets say:
Red, 50, Super Popular
Become a table of:
Name, Red
Hue, 50
Populatiry, Super Popular
Im basically using a function to replace a string value (entered as a what a columns name is) with its actual value and I cannot use the exec command as functions wont allow it and it has to be a function cause Im selecting that returned string directly into a procedure:
This is the code I had until I found exec commands stop it working as a function
CREATE FUNCTION [dbo].[GetOutlookTrainingBodyText]
(
#ScheduleID bigint
)
RETURNS nvarchar(300)
AS
BEGIN
declare c cursor local fast_forward
for
SELECT Label, Name, QueryField
FROM IntranetPagesx ipx
INNER JOIN IntranetPageLayoutx ipl on ipl.PageID = ipx.PageID
WHERE ipx.PageID = 'Training Attendance'
declare #name nvarchar (100)
declare #name1 nvarchar (100)
declare #label nvarchar (100)
declare #queryfield nvarchar (200)
declare #sql nvarchar (1000)
declare #BodyText nvarchar(500) = (SELECT dbo.GetValidSystemPropertyValue('OutlookIntegrationTrainingBodyTextTemplate'))
open c
fetch next from c into #label, #name, #queryfield
while ##FETCH_STATUS = 0
begin
SET #sql = 'SELECT TOP 1 #name1= '+#queryfield+' FROM TRAINING_AttendanceConfirmed WHERE ScheduleID = ''246'''
EXEC sp_executesql #sql,N'#name1 nvarchar(200) out', #name1 out
set #BodyText = Replace(#BodyText, '#'+#label+'#', (ISNULL(#name1, '')))
fetch next from c into #label, #name, #queryfield
END
CLOSE c
DEALLOCATE c
PRINT #BodyText
return (#BodyText)
END
I need the working equivalent without the use of exec - can this be done????
xml can provide some flexibility to handle column names and values, something like this:
SELECT
CAST(CAST((SELECT TOP 1 * FROM colours FOR XML PATH('')) AS XML).query('fn:local-name(*[1]/.)') AS VARCHAR(100)) colname,
CAST(CAST((SELECT TOP 1 * FROM colours FOR XML PATH('')) AS XML).query('*[1]/text()') AS VARCHAR(100)) value
UNION
SELECT
CAST(CAST((SELECT TOP 1 * FROM colours FOR XML PATH('')) AS XML).query('fn:local-name(*[2]/.)') AS VARCHAR(100)) colname,
CAST(CAST((SELECT TOP 1 * FROM colours FOR XML PATH('')) AS XML).query('*[2]/text()') AS VARCHAR(100)) value
UNION
SELECT
CAST(CAST((SELECT TOP 1 * FROM colours FOR XML PATH('')) AS XML).query('fn:local-name(*[3]/.)') AS VARCHAR(100)) colname,
CAST(CAST((SELECT TOP 1 * FROM colours FOR XML PATH('')) AS XML).query('*[3]/text()') AS VARCHAR(100)) value

How to Return Single row?

When i am check the Multi-line function
select * from calculation('2')
Error:
Hi after google i came to know that it's returning two rows(multiple rows) but no idea how to slove this can any give me suggestion please
enter code here
ALTER FUNCTION [dbo].[calculation]
(#AgentID int)
RETURNS #CustomerPosition TABLE
(
-- Add the column definitions for the TABLE variable here
DayAmount Decimal Not NULL,
MonthAmount Decimal NOT NULL,
YearAmount Decimal NOT NULL,
Position INT NOT NULL
)
AS
BEGIN
-- Fill the table variable with the rows for your result set
INSERT Into #CustomerPosition(DayAmount,MonthAmount,YearAmount,Position)
Declare #DayAmount as Decimal
set #DayAmount = (select sum(AmountRecevied) as Totoalamountperday from
tblcollections
where AgentID=#AgentID and datepart(dd,Date_Time)= DATEPART(DD,GETDATE())
group by AgentID)
--SET NOCOUNT ON
DECLARE #MonthStartDate As datetime
DECLARE #MonthEndDate As datetime
DECLARE #today datetime
set #today = convert(varchar(12) , getdate() , 101)
SET #MonthStartDate = #today
Declare #MonthAmount as Decimal
set #MonthAmount = (select sum(AmountRecevied)as Totoalamountperday from
tblcollections
where AgentID=#AgentID and Date_Time between dateadd(dd,- datepart(dd,#MonthStartDate),#MonthStartDate+1) and dateadd(dd,-1,dateadd(mm,+1,#MonthStartDate))
group by AgentID)
Declare #YearAmount as Decimal
set #YearAmount=(select sum(AmountRecevied) as Totoalamountpermonth from
tblcollections
where AgentID=#AgentID and datepart(YYYY,Date_Time) =YEAR(GETDATE())
group by AgentID)
Declare #Position as Decimal
set #Position = (select [RowNumber] = ROW_NUMBER() OVER(ORDER BY AgentID DESC) from
tblcollections
where AgentID=#AgentID
group by AgentID
)
RETURN
END
Try something like this:
SELECT TOP 1 ...

How to Dynamically Add to the TSQL Where Clause in a Stored Procedure

How to dynamically add conditions to the TSQL Where clause? I'm trying to avoid selecting between two complete Select statements. The following is very similar, but less complicated, than my actual code.
SELECT COUNT(*)
FROM MyTable
WHERE ShipDate >= #FirstDayOfMonth
AND ShipDate < #LastDayOfMonth
AND OrderType = 1
AND NOT OrderCode LIKE '%3'
AND NOT OrderCode LIKE '%4';
I would like to be able to add or remove the last two conditions depending on the value of a stored procedure parameter. i.e.: if #ExcludePhoneOrders = False , don't use the last two Where clause conditions.
I'm not sure if you meant to include or exclude, but here is a stab at it.
SELECT COUNT(*)
FROM MyTable
WHERE ShipDate >= #FirstDayOfMonth
AND ShipDate < #LastDayOfMonth
AND OrderType = 1
AND (#ExcludePhoneOrders = False OR (NOT OrderCode LIKE '%3' AND NOT OrderCode LIKE '%4'));
It should look something like this...
If the datatype I used is not right, you should change them.
But the main concept should remain the same.
Let me know how it goes.
Create proc GetOrders
....,
#FirstDayOfMonth int,
#LastDayOfMonth int,
....
AS
DECLARE #SQL varchar(1000)
DECLARE #PARAMS nvarchar(100);
set #SQL='SELECT COUNT(*) FROM MyTable WHERE ShipDate >= #FirstDay_OfMonth AND ShipDate < #LastDay_OfMonth AND OrderType = 1';
if(#ExcludePhoneOrders = 1)
begin
set #SQL=#SQL + ' AND NOT OrderCode LIKE ''%3'' AND NOT OrderCode LIKE ''%4'''
end
SET #PARAMS = '#FirstDayOfMonth int, #LastDayOfMonth int'
EXECUTE sp_executesql #SQL, #PARAMS, #FirstDay_OfMonth = #FirstDayOfMonth, #LastDay_OfMonth=#LastDayOfMonth
GO
You could dump the query to a varchar, then use an if statement to optionally append the extra where clause info, then pass the whole thing to sp_executesql.
SELECT COUNT(*)
FROM MyTable
WHERE ShipDate >= #FirstDayOfMonth
AND ShipDate < #LastDayOfMonth
AND OrderType = 1
AND (
(#ExcludePhoneOrders <> False AND NOT OrderCode LIKE '%3' AND NOT OrderCode LIKE '%4')
OR
#ExcludePhoneOrders = False
)
You need consider handle NULL value if parameter can be NULL

Resources