So I have a drop down list(ASP.NET) with some values retrieved from sqldatasource. And I added a item name 'ALL' with a value -1 to retrieve all the values in that field(the field is varchar). But it do-sent work. Please help how can i get all the values instead of a specific one.
the 'All' Value is -1 witch is passed to the parameter #NAME but it do-sent work
Query:
SELECT USERINFO.USERID, USERINFO.NAME, USERINFO.TITLE,
CHECKINOUT.CHECKTIME, CHECKINOUT.CHECKTYPE FROM USERINFO INNER JOIN
CHECKINOUT ON USERINFO.USERID = CHECKINOUT.USERID WHERE NAME = #NAME
AND CHECKTIME BETWEEN #startDate AND #endDate + ' 23:59:00.000'
SELECT USERINFO.USERID, USERINFO.NAME, USERINFO.TITLE,
CHECKINOUT.CHECKTIME, CHECKINOUT.CHECKTYPE FROM USERINFO INNER JOIN
CHECKINOUT ON USERINFO.USERID = CHECKINOUT.USERID
WHERE ( NAME = #NAME and #NAME<> -1 ) OR (#NAME = -1 and 1=1)
AND CHECKTIME BETWEEN #startDate AND #endDate + ' 23:59:00.000'
Basically , the condition 1=1 is used to ignore condition in where clause for particular value passed to variable , in this case #NAME
Related
I have a stored procedure which provides different result based on the input parameter supplied. I need to execute the procedure and cast the result into a data table to show in the grid. How can I do that? Do I need to create a model for all the outcomes or is there any generic way to do it?
--There are lots of report type. Just listed 2 of them for now
CREATE PROCEDURE [dbo].[uspGetAdminReportData]
#reportType VARCHAR(50)
AS
BEGIN
IF(#reportType = 'TOTAL_BY_DATE')
BEGIN
SELECT CONVERT(VARCHAR, DATE_SENT, 111) AS Date_Sent, FORMAT(DATE_SENT, 'dddd') AS Day_Of_Week, COUNT(*) AS Email_Count FROM TBLDATA1 WITH(NOLOCK) GROUP BY DATE_SENT
END
ELSE IF (#reportType = 'USER_LOGIN_LOGOUT_REPORT')
BEGIN
SELECT UserName, CONVERT(VARCHAR(10), [LOGIN], 111) AS LOGIN_DATE, CONVERT(VARCHAR(3),(SUM(DATEDIFF(MINUTE,[LOGIN],[LOGOUT]))/60)) + ':' + RIGHT('00' + CONVERT(VARCHAR(3),(SUM(DATEDIFF(MINUTE,[LOGIN],[LOGOUT])) - (SUM(DATEDIFF(MINUTE,[LOGIN],[LOGOUT]))/60) * 60)),2) AS TOTAL_TIME FROM USERAUDIT WITH(NOLOCK)
INNER JOIN
UserRecords WITH(NOLOCK) ON UserAudit.UserId = UserRecords.UserId
Where DateDiff(Minute, [Login], [LOGOUT]) > 0
GROUP BY UserRecords.UserName, CONVERT(VARCHAR(10), [LOGIN], 111)
ORDER BY UserRecords.UserName, CONVERT(VARCHAR(10), [LOGIN], 111)
END
END
C# code
public virtual DataTable GetAdminReportData(ReportType reportType)
{
//not sure how to get the result executing the procedure for various report types. Need to execute the procedure, and cast the result as a data table and return to load table to the grid using entity framework
SqlParameter ReportType = new SqlParameter("reportType", reportType.ToString());
var result = this.Database.SqlQuery<object>("uspGetAdminReportData #reportType", ReportType);
}
I have a SQL query that is being used in a C# controller class to return search query results:
SELECT #Output = (SELECT Name, Id
FROM [dbo].[Users]
WHERE Name = 'Robert');
However, when I run this query, I get the following error:
Only one expression can be specified in the select list when the subquery is not introduced with EXISTS.
I know that simply removing one of the column names will fix the issue, but I want to be able to return the Name and ID for each searched user.
Is there a way to change my query so that I can return the desired columns and still keep my #Output parameter in the query? Any recommendations would be much appreciated
One method is to concatenate them:
SELECT #Output = (SELECT Name + '|' + CONVERT(VARCHAR(255), Id)
FROM [dbo].[Users]
WHERE Name = 'Robert'
);
Another alternative is to use two variables, because you want two items:
SELECT #Name = Name, #Id = Id
FROM [dbo].[Users]
WHERE Name = 'Robert';
Given that you know that the name is 'Robert', I don't see why that is useful. You can do:
DECLARE #Name VARCHAR(255);
SET #Name = 'Robert';
SELECT #Id = Id
FROM [dbo].[Users]
WHERE Name = #Name;
Not sure if this is what you were looking for, you can declare #output as table, and insert the values when condition is true.
Declare #output table ([name] varchar(50), ID int)
insert into #output([name], id) select 'abc', 1
select * from #output
Output: This is just sample data
name ID
abc 1
I'm passing a string variable to an IN Clause in sql (Stored Procedure). When declaring and setting the variable in sql I get back all the data that is required. But when setting the variable from c# I'm only receiving data based on the first status within that paramater.
I've got a function to split the statuses in the paramater list to retrieve the records:
ALTER FUNCTION [dbo].[fnSplit](
#sInputList VARCHAR(8000)
, #sDelimiter VARCHAR(10) = ';'
) RETURNS #List TABLE (item VARCHAR(8000))
BEGIN
DECLARE #sItem VARCHAR(8000)
WHILE CHARINDEX(#sDelimiter,#sInputList,0) <> 0
BEGIN
SELECT
#sItem=RTRIM(LTRIM(SUBSTRING(#sInputList,1,CHARINDEX(#sDelimiter,#sInputList,0)-1))),
#sInputList=RTRIM(LTRIM(SUBSTRING(#sInputList,CHARINDEX(#sDelimiter,#sInputList,0)+LEN(#sDelimiter),LEN(#sInputList))))
IF LEN(#sItem) > 0
INSERT INTO #List SELECT #sItem
END
IF LEN(#sInputList) > 0
INSERT INTO #List SELECT #sInputList
RETURN
END
My stored procedure is built like this:
ALTER procedure [dbo].[Get_RequestsAtEachStage]
(#managerRef int,
#status varchar(20))
as
BEGIN
WITH MaxStatusDate
as
(
select rs.requestID,rs.status from (
SELECT requestID,MAX([DateCreated]) AS MaxDate
FROM [LoanRequest].[dbo].[requestStatus]
GROUP BY RequestID) maxg
inner join [LoanRequest].[dbo].[requestStatus] rs on maxg.requestid = rs.requestid and maxg.MaxDate = rs.DateCreated
)
SELECT lr.ID, lr.serialNo, lr.model, lr.clientName, lr.address, lr.telephone, lr.contactName,
lr.swop, lr.substitueOfGoods, lr.printFunction, lr.copyFunction, lr.scanFunction,
lr.faxFunction, lr.controller, lr.controllerEmailAddress,
ml.Name, wl.Location, rt.requestType AS RequestTypeName, rs.status
FROM [dbo].[loanRequest] lr
INNER JOIN [dbo].[managersList] ml ON lr.managerRef = ml.ID
INNER JOIN [dbo].[warehouseList] wl ON lr.warehouseID = wl.ID
INNER JOIN [dbo].[requestType] rt ON lr.requestType = rt.ID
INNER JOIN MaxStatusDate rs ON lr.ID = rs.requestID
WHERE (#managerRef is null or lr.managerRef = #managerRef) AND rs.status IN (SELECT item FROM [dbo].[fnSplit](#status, ';'))
END
Based on the page the user access it will send through the appropriate statusses and retrieve the necessary records.
Setting the paramaters in sql as follows works perfect, I retrieve all the records:
DECLARE #managerRef INT
DECLARE #status NVARCHAR(100)
SET #managerRef = NULL
SET #status = 'Allocated;Readings Updated'
But, when I send it through c# within a string, it only retrieves records with the status of Allocated.:
string status = "Allocated;Readings Updated";
DataTable dtDevices = d.PopulateDevicesApproval(managerRef, status);
My method to retrieve the data from sql:
string filterstring = "";
filterstring = "Get_RequestsAtEachStage ";
cn = new SqlConnection(GetConnectionString());
SqlCommand myCmd = new SqlCommand(filterstring, cn);
myCmd.CommandType = CommandType.StoredProcedure;
cn.Open();
myCmd.Parameters.AddWithValue("#managerRef", managerRef);
myCmd.Parameters.AddWithValue("#status", status);
DataTable dt = new DataTable();
dt.Load(myCmd.ExecuteReader());
return dt;
Is there anything I am doing wrong?
--------- EDIT -----------
Running SELECT item FROM [dbo].fnSplit results from both c# and sql
Returning results from c#:
And returning results from sql:
I have one temp table in sql.
CREATE TABLE #Temporary(ColumnNames varchar(100),IsActive varchar(100))
insert into #Temporary(ColumnNames,IsActive)
select aa.Name,bb.IsActive from tableAA aa join tableBB bb on aa.Id = bb.Id
ColumnNames IsActive
Name 1
Description 1
Id 0
Now I want to traverse through each ColumnNames and pass that value to another select query
and take out its related value from another table using join if IsActive =1
for example, I did it in c# code I need to convert this code in SQL code
new string s1
forloop(END OF ALL COLUMNS FROM #Temporary){
if(isactive=0)
concatinate string s1 +=cloumnIndex[i]+','
else
concatinate string s1 +='(select resourcetableValue from ResourcesTable as t where contry.'+cloumnIndex[i]+'=t.resourcetableKey),'
}
EXEC('select '+string s1 +' from vwCountry as contry')
I need to create String s1 which will take out all column names from Temp Table and for loop else part will populate values using join and at the end EXEC statement executes all query at once
Try this
DECLARE #i INT=1,
#s1 NVARCHAR(max)=''
WHILE(#i<=##ROWCOUNT)
BEGIN
SELECT #s1+= CASE WHEN isactive=1 THEN '(select resourcetableValue .......<your condition>'
ELSE ''
from #temporary WHERE id=#i
SET #i=#i+1
END
exec sp_executesql #S1
To write your loop "as is" can be done with:
declare #s nvarchar(4000) = '';
select #s = #s + case IsActive when 0 then ColumnNames + ','
else '(select resourcetableValue from ResourcesTable as t where contry.'
+ ColumnNames + '=t.resourcetableKey),' end
from #Temporary
exec ('select ' + #s + ' from vwCountry as contry')
you probably want to remove the last comma between the select and the exec, though
I have a table DEPT, which holds 2 columns - ID, NAME.
A search form is presented with the IDs from the DEPT table and the user can chose any number of IDs and submit the form, to get the related NAMEs.
Clarification/Inputs:
I don't want to build a dynamic query - its not manageable.
I prefer a stored procedure using table-valued parameters
Any other solutions to proceed?
NOTE:
This example is simple with 1 table - in real life, I have to deal with more than 6 tables!
Thanks for any suggestions
CREATE TYPE dbo.DeptList
AS TABLE
(
ID INT
);
GO
CREATE PROCEDURE dbo.RetrieveDepartments
#dept_list AS dbo.DeptList READONLY
AS
BEGIN
SET NOCOUNT ON;
SELECT Name FROM dbo.table1 WHERE ID IN (SELECT ID FROM #dept)
UNION ALL
SELECT Name FROM dbo.table2 WHERE ID IN (SELECT ID FROM #dept)
-- ...
END
GO
Now in your C# code, create a DataTable, fill it in with the IDs, and pass it in to the stored procedure. Assuming you already have a list called tempList and the IDs are stored in id:
DataTable tvp = new DataTable();
tvp.Columns.Add(new DataColumn("ID"));
foreach(var item in tempList)
{
tvp.Rows.Add(item.id);
}
using (connObject)
{
SqlCommand cmd = new SqlCommand("StoredProcedure", connObject);
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter tvparam = cmd.Parameters.AddWithValue("#dept_list", tvp);
tvparam.SqlDbType = SqlDbType.Structured;
...
}
You can also use a split function. Many exist, this is the one I like if you can guarantee that the input is safe (no <, >, & etc.):
CREATE FUNCTION dbo.SplitInts_XML
(
#List VARCHAR(MAX),
#Delimiter CHAR(1)
)
RETURNS TABLE
AS
RETURN
(
SELECT Item = y.i.value('(./text())[1]', 'int')
FROM
(
SELECT x = CONVERT(XML, '<i>'
+ REPLACE(#List, #Delimiter, '</i><i>') + '</i>').query('.')
) AS a
CROSS APPLY x.nodes('i') AS y(i)
);
GO
Now your procedure can be:
CREATE PROCEDURE dbo.RetrieveDepartments
#dept_list VARCHAR(MAX)
AS
BEGIN
SET NOCOUNT ON;
;WITH d AS (SELECT ID = Item FROM dbo.SplitInts(#dept_list, ','))
SELECT Name FROM dbo.table1 WHERE ID IN (SELECT ID FROM d)
UNION ALL
SELECT Name FROM dbo.table2 WHERE ID IN (SELECT ID FROM d)
-- ...
END
GO