Must declare the scalar variable "#dom" - c#

This is a bit confusing because it worked before and I added 1 little change and I get this error message in my web application. (I do have other cases, I just took out the other cases for simplicity)
Original code that worked before:
ALTER PROCEDURE [dbo].[GetRoles]
(#reportid Decimal, #dom varchar(10))
AS
DECLARE #sql varchar(2000)
SELECT #sql =
Case #reportid
WHEN 1 THEN
'select u.id as userId, u.domain, u.isAdmin, u.email, u.canReport, a.[site], a.bldgNum, a.dataCenterNum, l.shortName, l.[description], a.canApprove, a.canComplete
from locAdmin a
inner join location l on (a.site=l.site and a.bldgNum = l.bldgNum and a.dataCenterNum = l.dataCenterNum)
right outer join [user] u on u.id=a.userId and u.domain=a.domain
where u.isAdmin = 1'
End
EXEC (#sql)
The only change I did was adding
and u.domain = #dom'
after where u.isAdmin = 1' at the end so it looks like this
where u.isAdmin = 1 and u.domain = #dom'

You need to add #dom as a parameter when you execute your dynamic SQL.
Replace EXEC (#sql) with exec sp_executesql #sql, N'#dom varchar(10)', #dom and change DECLARE #sql varchar(2000) to DECLARE #sql nvarchar(2000).

You don't need dynamic SQL to to this write this query.
Please do it like this:
ALTER PROCEDURE [dbo].[GetRoles]
(
#reportid Decimal,
#dom varchar(10)
)
AS
select u.id as userId, u.domain, u.isAdmin, u.email, u.canReport,
a.[site], a.bldgNum, a.dataCenterNum,
l.shortName, l.[description],
a.canApprove, a.canComplete
from locAdmin a
inner join location l
on a.site=l.site and a.bldgNum = l.bldgNum and a.dataCenterNum = l.dataCenterNum
right outer join [user] u
on u.id=a.userId and u.domain=a.domain
where u.isAdmin = 1 and u.domain = #dom and #reportid = 1

You need to actually add the value of the variable to your dynamic SQL:
'THE REST OF YOUR QUERY
where u.isAdmin = 1 and u.domain = ''' + #dom + ''''
This is because your dynamic SQL is another SQL statement that you are going to execute, and therefore doesn't know about the parameter #dom in your original statement.

Related

Best way to write Combination logic in SQL or MVC for multiple select options

I, want to write the best combination login either SQL store procedure or ASP.net for the following combination diagram.
Each field in the diagram has 4 combinations. So, total it will be 20 combinations. I, don't want to write 20 if else statement in SQL server or c#.
Here is the UI for the logic.
The user can either select Quotation no or combination of 20 etc. I, don't want to write 20 if else statement.
Is their any better way to write a statement in SQL or C# to make it better.
For example
the user can select from either Quotation no or agency name or start date or end date or combination of two or more field.
What is the best way to write the algorithm?
Here is the combination
1- Search By only Quotation No
2- Search By only Agency No
3- Search By only Start Date
4- Search By only End Date
5- Search By only contract No
6 - Quotation No + Agency No
7 - Quotation No + Start Date
8 - Quotation No + End Date
9 - Select by All fields
I stumbled upon a similar problem some time ago while trying to perform a search using many filters. The best solution I found was to use a dynamic SQL query, in which the statement is built based on the parameters.
The select clause of the sql statement is static but the from clause and the where clause is based on the parameters.
CREATE PROCEDURE dbo.SearchQuotation
(
#QuotationNo INT,
#AgencyName VARCHAR(50),
#StartDate DATETIME,
#EndDate DATETIME,
#Term INT
)
AS
BEGIN
DECLARE #SQL NVARCHAR(4000)
SELECT #SQL = N'SELECT * FROM Quotations WHERE 1 = 1'
DECLARE #ParametersDefinition NVARCHAR(4000)
SELECT #ParametersDefinition = N'#QuotationNoParameter INT,
#AgencyNameParameter VARCHAR(50),
#StartDateParameter DATETIME,
#EndDateParameter DATETIME,
#TermParameter INT'
IF #QuotationNo IS NOT NULL
SELECT #SQL = #SQL + N' AND QuotationNo = #QuotationNoParameter '
IF #AgencyName IS NOT NULL
SELECT #SQL = #SQL + N' AND AgencyName = #AgencyNameParameter '
IF #StartDate IS NOT NULL
SELECT #SQL = #SQL + N' AND StartDate = #StartDateParameter '
IF #EndDate IS NOT NULL
SELECT #SQL = #SQL + N' AND EndDate = #EndDateParameter '
IF #Term IS NOT NULL
SELECT #SQL = #SQL + N' AND Term = #TermParameter '
EXECUTE sp_executesql
#SQL,
#ParametersDefinition,
#QuotationNoParameter = #QuotationNo,
#AgencyNameParameter = #AgencyName,
#StartDateParameter = #StartDate,
#EndDateParameter = #EndDate,
#TermParameter = #Term
END
From the SQL side you can achieve by this way:
SELECT * FROM Qoutes AS q
WHERE (q.QoutationNo = #QoutationNo OR #QoutationNo IS NULL)
AND (q.AgencyName = #AgencyName OR #AgencyName IS NULL)
AND (q.StartDate = #StartDate OR #StartDate IS NULL)
AND (q.EndDate = #EndDate OR #EndDate IS NULL)
AND (q.Term = #Term OR #Term IS NULL)
Pass NULL value if it is not selected from the web page.

SQL Server: return the result of a select as a result of stored procedure execution

I have a stored procedure that is called from C#:
CREATE PROCEDURE [MySP]
#ID int,
#Exists bit OUTPUT
AS
BEGIN
SET NOCOUNT ON;
SET #Exists = 0
SELECT TOP 1 ID
FROM MyTable
WHERE ID = #ID
IF ##ROWCOUNT = 0
BEGIN
SELECT b.*
FROM AnotherTable b
INNER JOIN AnotherTable2 c ON b.ID = c.ID
WHERE b.ID = #ID
END
ELSE
BEGIN
SET #Exists = 1
SELECT TOP 0 NULL
END
END
IF #ID does not exist in table MyTable, then I return the SELECT b.*, otherwise if #ID exists in the table, then I return no rows
The problem is that when #ID exists in the table, the stored procedure returns two tables as a result to C#, the one from SELECT TOP 1 and the one from SELECT b.* and I only want to return SELECT b.* so how can I do this?
Just replace all the logic with:
SELECT b.*
From AnotherTable b INNER JOIN
AnotherTable2 c
ON b.ID = c.ID
WHERE b.ID = #ID AND
NOT EXISTS (SELECT 1 FROM MyTable WHERE ID = #ID);
And, if you don't want duplicates, you might as well do:
SELECT b.*
From AnotherTable b
WHERE b.ID = #ID AND
EXISTS (SELECT 1 FROM AnotherTable2 c WHERE b.ID = c.ID) AND
NOT EXISTS (SELECT 1 FROM MyTable WHERE ID = #ID);
Then, learn about table valued functions. If you want to return a table, then the best approach -- if it is feasible -- is a function, not a stored procedure.
(Functions are more limited in their functionality, so this is not always possible.)
Use exists for this:
CREATE PROCEDURE [MySP]
#ID int,
#Exists bit OUTPUT
AS
BEGIN
SET NOCOUNT ON;
SET #Exists = 0
IF EXISTS(SELECT TOP 1 ID FROM MyTable WHERE ID = #ID)
BEGIN
SELECT b.*
From AnotherTable b
INNER JOIN AnotherTable2 c on b.ID = c.ID
Where b.ID = #ID
END
ELSE
BEGIN
SET #Exists = 1
SELECT TOP 0 NULL
END
END
The second result that you are getting is from the statement select top 0 null

Stored Procedure giving different result on same database with same argument

I have a stored procedure which gives different result in only a specific case.
When I call it from SQL Server Management Studio 2008 R2, it gives me 0 as output.
When I call it from C# class file. It gives me 1 as output.
I am using edmx file, and it is updated for sure.
The call is something like below from SSMS [SQL Server Management Studio]
exec proc_GetPrimaryKeyUsageCount 62, 'tblFormula'
This gives output as 0
The same stored procedure is called from C# file is like below
_db.GetPrimaryKeyUsageCount(62, "tblFormula");
This gives output as 1
The stored procedure is
CREATE PROCEDURE proc_GetPrimaryKeyUsageCount (
#PrimaryKeyColumnId INT
,#PrimaryKeyTable NVARCHAR(max)
--,#Response INT OUTPUT
)
AS
BEGIN
DECLARE #counter INT
DECLARE #sqlCommand NVARCHAR(max)
DECLARE #ForeignKey TABLE (
child_table VARCHAR(max)
,child_fk_column VARCHAR(max)
)
DECLARE #child_table VARCHAR(max)
DECLARE #child_fk_column VARCHAR(max)
SET #counter = 0
INSERT INTO #ForeignKey
SELECT child_table = c.TABLE_NAME
,child_fk_column = c.COLUMN_NAME
FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE p
INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS pc ON pc.UNIQUE_CONSTRAINT_SCHEMA = p.CONSTRAINT_SCHEMA
AND pc.UNIQUE_CONSTRAINT_NAME = p.CONSTRAINT_NAME
INNER JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE c ON c.CONSTRAINT_SCHEMA = pc.CONSTRAINT_SCHEMA
AND c.CONSTRAINT_NAME = pc.CONSTRAINT_NAME
WHERE EXISTS (
SELECT 1
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME = 'IsDeleted'
AND TABLE_SCHEMA = p.TABLE_SCHEMA
AND TABLE_NAME = p.TABLE_NAME
AND p.TABLE_NAME = #PrimaryKeyTable
)
DECLARE db_cursor CURSOR
FOR
SELECT child_table
,child_fk_column
FROM #ForeignKey
OPEN db_cursor
FETCH NEXT
FROM db_cursor
INTO #child_table
,#child_fk_column
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT 'select count(*) from ' + CAST(#child_table AS VARCHAR) + ' where ' + CAST(#child_fk_column AS VARCHAR) + ' = ' + CAST(#PrimaryKeyColumnId AS VARCHAR)
SET #sqlCommand = 'select #cnt=count(*) from ' + CAST(#child_table AS VARCHAR) + ' where ' + CAST(#child_fk_column AS VARCHAR) + ' = ' + CAST(#PrimaryKeyColumnId AS VARCHAR)
EXEC sp_executesql #sqlCommand
,N'#cnt int OUTPUT'
,#cnt = #counter OUTPUT
IF #counter > 0
BREAK
FETCH NEXT
FROM db_cursor
INTO #child_table
,#child_fk_column
END
SELECT #counter AS [PrimaryKeyUsageCount]
END
1st argument is Id of the primary key and 2nd argument is the name of the table having that primary key.
The Procedure returns the count of the usage of primary key in other tables in same database. If it finds even 1 occurrence, it will return that count otherwise 0.
If anything extra is needed please do let me know.
There are couple of mistakes, which could cause the problem.
The INSERT should be like that:
INSERT INTO #ForeignKey
SELECT c.TABLE_NAME,c.COLUMN_NAME
FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE p
INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS pc ON pc.UNIQUE_CONSTRAINT_SCHEMA = p.CONSTRAINT_SCHEMA
AND pc.UNIQUE_CONSTRAINT_NAME = p.CONSTRAINT_NAME
INNER JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE c ON c.CONSTRAINT_SCHEMA = pc.CONSTRAINT_SCHEMA
AND c.CONSTRAINT_NAME = pc.CONSTRAINT_NAME
WHERE EXISTS (
SELECT *
FROM INFORMATION_SCHEMA.COLUMNS AS isc
WHERE isc.COLUMN_NAME = 'IsDeleted'
AND isc.TABLE_SCHEMA = p.TABLE_SCHEMA
AND isc.TABLE_NAME = p.TABLE_NAME
AND p.TABLE_NAME = #PrimaryKeyTable
)
After cursor loop shoud be:
CLOSE db_cursor
DEALLOCATE db_cursor

List of Tables names used in MVC Application [duplicate]

I'm looking at creating a basic ORM (purely for fun), and was wondering, is there a way to return the list of tables in a database and also the fields for every table?
Using this, I want to be able to loop through the result set (in C#) and then say for each table in the result set, do this (e.g. use reflection to make a class that will do or contain xyz).
Further to this, what are some good online blogs for SQL Server? I know this question is really about using system SPs and databases in Sql Server, and I am ok with general queries, so I'm interested in some blogs which cover this sort of functionality.
Thanks
Is this what you are looking for:
Using OBJECT CATALOG VIEWS
SELECT T.name AS Table_Name ,
C.name AS Column_Name ,
P.name AS Data_Type ,
C.max_length AS Size ,
CAST(P.precision AS VARCHAR) + '/' + CAST(P.scale AS VARCHAR) AS Precision_Scale
FROM sys.objects AS T
JOIN sys.columns AS C ON T.object_id = C.object_id
JOIN sys.types AS P ON C.system_type_id = P.system_type_id
WHERE T.type_desc = 'USER_TABLE';
Using INFORMATION SCHEMA VIEWS
SELECT TABLE_SCHEMA ,
TABLE_NAME ,
COLUMN_NAME ,
ORDINAL_POSITION ,
COLUMN_DEFAULT ,
DATA_TYPE ,
CHARACTER_MAXIMUM_LENGTH ,
NUMERIC_PRECISION ,
NUMERIC_PRECISION_RADIX ,
NUMERIC_SCALE ,
DATETIME_PRECISION
FROM INFORMATION_SCHEMA.COLUMNS;
Reference : My Blog - http://dbalink.wordpress.com/2008/10/24/querying-the-object-catalog-and-information-schema-views/
Tables ::
SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE'
columns ::
SELECT * FROM INFORMATION_SCHEMA.COLUMNS
or
SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='your_table_name'
Get list of all the tables and the fields in database:
Select *
From INFORMATION_SCHEMA.COLUMNS
Where TABLE_CATALOG Like 'DatabaseName'
Get list of all the fields in table:
Select *
From INFORMATION_SCHEMA.COLUMNS
Where TABLE_CATALOG Like 'DatabaseName' And TABLE_NAME Like 'TableName'
I tested a few solutions an found that
Select *
From INFORMATION_SCHEMA.COLUMNS
gives you the column info for your CURRENT/default database.
Select *
From <DBNAME>.INFORMATION_SCHEMA.COLUMNS
, without the < and >, gives you the column info for the database DBNAME.
SELECT * FROM INFORMATION_SCHEMA.COLUMNS
Your other inbuilt friend here is the system sproc SP_HELP.
sample usage ::
sp_help <MyTableName>
It returns a lot more info than you will really need, but at least 90% of your possible requirements will be catered for.
Just throwing this out there - easy to now copy/paste into a word or google doc:
PRINT '<html><body>'
SET NOCOUNT ON
DECLARE #tableName VARCHAR(30)
DECLARE tableCursor CURSOR LOCAL FAST_FORWARD FOR
SELECT T.name AS TableName
FROM sys.objects AS T
WHERE T.type_desc = 'USER_TABLE'
ORDER BY T.name
OPEN tableCursor
FETCH NEXT FROM tableCursor INTO #tableName
WHILE ##FETCH_STATUS = 0 BEGIN
PRINT '<h2>' + #tableName + '</h2>'
PRINT '<pre>'
SELECT LEFT(C.name, 30) AS ColumnName,
LEFT(ISC.DATA_TYPE, 10) AS DataType,
C.max_length AS Size,
CAST(P.precision AS VARCHAR(4)) + '/' + CAST(P.scale AS VARCHAR(4)) AS PrecScale,
CASE WHEN C.is_nullable = 1 THEN 'Null' ELSE 'No Null' END AS [Nullable],
LEFT(ISNULL(ISC.COLUMN_DEFAULT, ' '), 5) AS [Default],
CASE WHEN C.is_identity = 1 THEN 'Identity' ELSE '' END AS [Identity]
FROM sys.objects AS T
JOIN sys.columns AS C ON T.object_id = C.object_id
JOIN sys.types AS P ON C.system_type_id = P.system_type_id
JOIN INFORMATION_SCHEMA.COLUMNS AS ISC ON T.name = ISC.TABLE_NAME AND C.name = ISC.COLUMN_NAME
WHERE T.type_desc = 'USER_TABLE'
AND T.name = #tableName
ORDER BY T.name, ISC.ORDINAL_POSITION
PRINT '</pre>'
FETCH NEXT FROM tableCursor INTO #tableName
END
CLOSE tableCursor
DEALLOCATE tableCursor
SET NOCOUNT OFF
PRINT '</body></html>'
SELECT * FROM INFORMATION_SCHEMA.COLUMNS for get all
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.COLUMNS for get all table name.
Try it on sqlserver,
This will get you all the user created tables:
select * from sysobjects where xtype='U'
To get the cols:
Select * from Information_Schema.Columns Where Table_Name = 'Insert Table Name Here'
Also, I find http://www.sqlservercentral.com/ to be a pretty good db resource.
This will return the database name, table name, column name and the datatype of the column specified by a database parameter:
declare #database nvarchar(25)
set #database = ''
SELECT cu.table_catalog,cu.VIEW_SCHEMA, cu.VIEW_NAME, cu.TABLE_NAME,
cu.COLUMN_NAME,c.DATA_TYPE,c.character_maximum_length
from INFORMATION_SCHEMA.VIEW_COLUMN_USAGE as cu
JOIN INFORMATION_SCHEMA.COLUMNS as c
on cu.TABLE_SCHEMA = c.TABLE_SCHEMA and c.TABLE_CATALOG =
cu.TABLE_CATALOG
and c.TABLE_NAME = cu.TABLE_NAME
and c.COLUMN_NAME = cu.COLUMN_NAME
where cu.TABLE_CATALOG = #database
order by cu.view_name,c.COLUMN_NAME
For MYSQL:
Select *
From INFORMATION_SCHEMA.COLUMNS
where TABLE_SCHEMA = "<DatabaseName>"
I found an easy way to fetch the details of Tables and columns of a particular DB using SQL developer.
Select *FROM USER_TAB_COLUMNS
in a Microsoft SQL Server you can use this:
declare #sql2 nvarchar(2000)
set #sql2 ='
use ?
if ( db_name(db_id()) not in (''master'',''tempdb'',''model'',''msdb'',''SSISDB'') )
begin
select
db_name() as db,
SS.name as schemaname,
SO.name tablename,
SC.name columnname,
ST.name type,
case when ST.name in (''nvarchar'', ''nchar'')
then convert(varchar(10), ( SC.max_length / 2 ))
when ST.name in (''char'', ''varchar'')
then convert(varchar(10), SC.max_length)
else null
end as length,
case when SC.is_nullable = 0 then ''No'' when SC.is_nullable = 1 then ''Yes'' else null end as nullable,
isnull(SC.column_id,0) as col_number
from sys.objects SO
join sys.schemas SS
on SS.schema_id = SO.schema_id
join sys.columns SC
on SO.object_id = SC.object_id
left join sys.types ST
on SC.user_type_id = ST.user_type_id and SC.system_type_id = ST.system_type_id
where SO.is_ms_shipped = 0
end
'
exec sp_msforeachdb #command1 = #sql2
this shows you all tables and columns ( and their definition ) from all userdefined databases.

Dynamic Where Clause - Some variables not passing

I was wondering if the below scenario will work? I am having trouble with it.
I have a smart tag SQLDataSource with a query like such:
SELECT [col1], [col2], [col3] FROM [Table1] WHERE (#SubType = #SubID) ORDER BY [col1] ASC
No matter where or how I set the #SubType parameter, it does not work, yet if I change the query to WHERE [col1] = #SubID (removing the #SubType) it works fine.
Can I set a parameter as a field name to compare against like my query does?
That's not how parameters work. Parameters are not string replacement. They work with values, not database objects names (Columns, Tables, etc.).
The solution is to first assemble the SQL query with the desired columns (code behind) and then set the parameter's values.
If you want to dynamically replace the items in your WHERE clause then you will want to look at using Dynamic SQL, then you can build your SQL as a string and execute it.
Code sample from http://www.sommarskog.se/dynamic_sql.html
DECLARE #sql nvarchar(2000)
SELECT #sql = 'SELECT O.OrderID, SUM(OD.UnitPrice * OD.Quantity)
FROM dbo.Orders O
JOIN dbo.[Order Details] OD ON O.OrderID = OD.OrderID
WHERE O.OrderDate BETWEEN #from AND #to
AND EXISTS (SELECT *
FROM dbo.[Order Details] OD2
WHERE O.OrderID = OD2.OrderID
AND OD2.ProductID = #prodid)
GROUP BY O.OrderID'
EXEC sp_executesql #sql, N'#from datetime, #to datetime, #prodid int',
'19980201', '19980228', 76
Another helpful link:
Dynamic WHERE Clause

Categories

Resources