Insight.database executing sql function - sql

To execute sql function or procedure Insight database in the guts executes a query to get info about stored procedures or function and its parameters.
But in the case of sql function query returns the first parameter name empty.
for example:
exec sp_executesql N'SELECT ParameterName = p.Name, SchemaName = s.name, TypeName = t.Name
FROM sys.parameters p
LEFT JOIN sys.types t ON (p.user_type_id = t.user_type_id)
LEFT JOIN sys.schemas s ON (t.schema_id = s.schema_id)
WHERE p.object_id = OBJECT_ID(#Name)',N'#Name nvarchar(4000)', #Name=N'dbo.FuncName'
This query returns parameters list, but first parameter is empty.
In this case Insight.Database fails to execute query.
Is there a way to resolve it without using adapter?

As far as I know, there's no way for a SqlCommand to execute a SQL function directly (regardless of whether the parameters are correct).
To call a function directly, you would need to use a SQL statement. Example:
select * from dbo.fn_GetUserId_Username(#Username)
In this case, Insight should pick up the parameters correctly.

Related

Getting a list of all current scalar variables

I'm trying to run the following code:
IF #tabla IS NULL
BEGIN
Declare #tabla VARCHAR(50)
END
Of course this gives me the undecleared variable error in sql, so I thought if there is a temp table like tempdb for scalar variables I could just look for the actaul name "tabla" in this table.
No, there's not a view to find variables in code. Variables that are not declared will prevent the code to compile and, therefore, to be stored. If you want to find a definition of the variable used in different code, you would need to search for it in the whole code which might give you false positives.
SELECT *
FROM sys.sql_modules
WHERE definition LIKE '%#tabla[^A-Za-z0-9]%'
The only thing that gets close to storing variables, is the sys.parameters table. But as the name states, it only shows parameters.
SELECT o.name AS ObjectName,
p.name AS ParameterName,
p.parameter_id,
t.name AS type,
p.max_length,
p.precision, p.scale,
p.is_output,
p.has_default_value,
p.is_nullable
--,any other columns
FROM sys.parameters p
JOIN sys.objects o ON p.object_id = o.object_id
JOIN sys.types t ON p.user_type_id = t.user_type_id;
Must declare the scalar variable "#tabla"
As the error states, you have to declare the "#tabla" before your IF statement. You wont be able to achieve this even after you look for the correct "tabla" name from system table. The scope of the variable last for the duration the stored procedure.

SQL Server 2016: select * from sys.objects returns different result when run from a stored procedure

I have the following query
SELECT *
FROM sys.objects
WHERE type = 'P' AND name = 'MySP'
When ran in a query window it gives the needed result. But when I run it in a stored procedure, it returns nothing.
Here is the code in the stored procedure:
declare #ProcName nvarchar(255) = 'MySP'
IF NOT EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = #ProcName)
THROW 51000, N'NOT_IMPLEMENTED',1;
The 'MySP' procedure is new, do I need to refresh cache or something? What am I missing here?
The IF statement throws the error e.g. it does not find any results, which there should be. I even tried to use just the exact same select as in my query window and it does not return results.

Passing the results of a query to a parameter in a stored procedure

I am trying to get the results of a stored procedure by passing the results of the query to my parameter.
ALTER PROCEDURE [DWH].[spAMBSiteAssetCountReport]
#Areaname, #SiteType, #EquipmentClass, #AssetStatus
#MaintenanceLocation varchar(Max),
#FLClassDescription varchar(max),
#EquipmentClass varchar(max),
#AssetStatus varchar(max)
As
Begin
SET NOCOUNT ON;
SET ANSI_WARNINGS OFF -- to suppress warning "string or binary data would be truncated"
SELECT
EC.ClassDescription, FL.Site,
SUBSTRING(FL.Site, CHARINDEX('-',FL.Site)+1,LEN(FL.Site)) SiteNo,
FL.SiteDesc, FL.FunctionalLocation, FL.Parish,
ST.SiteTypeName FLClassDescription, FL.MaintenanceLocationDesc,
Count(1) AS AssetCount
FROM
DWH.DimFunctionalLocation AS FL
INNER JOIN
DWH.DimEquipment AS EQ ON EQ.FunctionalLocationKey = FL.DW_FunctionalLocation_Key
INNER JOIN
DWH.DimEquipmentDetail AS EQD ON EQ.DW_Equipment_Key = EQD.EquipmentKey
INNER JOIN
DWH.DimEquipmentClass AS EC ON EC.DW_EquipmentClass_Key = EQD.DW_EquipmentDetail_Key
INNER JOIN
DWH.DimSiteType ST ON FL.SiteTypeKey = ST.DW_SiteType_Key
INNER JOIN
(select Item
from DWH.fnSplit(#FLClassDescription,',')) AS DNO ON (FL.SiteTypeKey = DNO.Item OR #FLClassDescription ='-1')
INNER JOIN
(select Item from DWH.fnSplit(#MaintenanceLocation,',')) AS ML ON (FL.MaintenanceLocationKey = ML.Item OR #MaintenanceLocation ='-1')
INNER JOIN
(select Item from DWH.fnSplit(#EquipmentClass,',')) AS FLC ON (EC.DW_EquipmentClass_Key = FLC.Item OR #EquipmentClass ='-1')
INNER JOIN
(select Item from DWH.fnSplit(#AssetStatus,',')) AS EQC ON ((EQD.CharacteristicName = EQC.Item AND ISNULL(LTRIM(RTRIM(EQD.CHARCharacteristicValue)),'') <> '') OR #AssetStatus ='All')
WHERE
FL.FLClassDescription IS NOT NULL
GROUP BY
EC.ClassDescription, FL.Site, FL.SiteDesc,
FL.FunctionalLocation, FL.Parish, ST.SiteTypeName,
FL.MaintenanceLocationDesc
END
I get results when I run the query but I need to pass the results to my parameter to get only distinct values for Equipment Class. The exec statement is below:
Exec DWH.spAMBSiteAssetCountReport #MaintenanceLocation=N'366,367,332,362,3,360,331,365,361,364,357,396,2,406,371,4,368,369,370,333,394,358,359,395,355,353,354,335,363,356,397,352,349,348,351,350,347,372,373,374,377,375,376,382,386,383,387,384,389,381,391,378,385,379,380,388,390',#FLClassDescription=N'3,4,5,2,1',#EquipmentClass = AssetCount,#AssetStatus=N'All'
I get a syntax error when trying to execute the stored procedure using the Asset Count as a valued parameter. Any help on this would be appreciated.
Thanks.
First, you declare the #AssetStatus parameter twice.
Second, you alias the count column as 'AssetCount', but don't use it anywhere else, so I'm not sure why you think that is causing a syntax error.
Lastly, you ask:
"I am trying to get the results of a stored procedure by passing the results of the query to my parameter."
What does this mean? Are you trying to recursively call a stored procedure from itself? Or are you trying to pass the results of another query INTO this stored procedure? More detail will help! If you respond with a comment I will try to help you along with this one - whatever your problem is, I don't think it'll be difficult to solve.

Query to get the information of Databases used by Stored Procedure in SQL server 2005

Is there any query in SQL server 2005 that returns the list of Stored procedures in the particular database along with the name of databases whose objects are getting used in the stored procedure.
That is how to get all procedure names:
select *
from DatabaseName.information_schema.routines
where routine_type = 'PROCEDURE'
I will check now, if there is any way to check their code for table names.
you can use this query
it will show all dependencies even to the columns
SELECT
--SP, View, or Function
ReferencingName = o.name,
ReferencingType = o.type_desc,
--Referenced Field
ref.referenced_database_name, --will be null if the DB is not explicitly called out
ref.referenced_schema_name, --will be null or blank if the DB is not explicitly called out
ref.referenced_entity_name,
ref.referenced_minor_name
FROM sys.objects AS o
cross apply sys.dm_sql_referenced_entities('dbo.' + o.name, 'Object') ref
where o.type = 'p'
-- for other database object types use below line
-- o.type in ('FN','IF','V','P','TF')
works for single database
select *
from information_schema.routines
where routine_type = 'PROCEDURE'
This is not a simple thing to do reliably in SQL Server 2005. You might want to look at commercial products such as ApexSQL Clean or SQL Dependency Tracker.
In SQL Server 2008 you could try using the sys.sql_expression_dependencies dynamic management view. For example,
select
quotename(s.name) + N'.' + quotename(o.name) as ProcedureName,
ed.referenced_server_name,
ed.referenced_database_name,
ed.referenced_schema_name,
ed.referenced_entity_name
from sys.sql_expression_dependencies ed
inner join sys.objects o on o.object_id = ed.referencing_id
inner join sys.schemas s on s.schema_id = o.schema_id
where
o.type = 'P'
Hope this helps,
Rhys

How to EXEC a query generated in a CTE

I have a CTE in which a SELECT statement is generated, but SQL Server (2012) does not allow calling EXEC on it. Here's the query:
DECLARE #guidToFind uniqueidentifier = 'E4069560-091A-4026-B519-104F1C7693B3';
WITH GuidCols (TableName, ColName, Query) As
(
SELECT
C.TABLE_NAME,
C.COLUMN_NAME,
'SELECT ' +
QUOTENAME(C.TABLE_NAME) + '.' +
QUOTENAME(C.COLUMN_NAME) + '
FROM ' +
QUOTENAME(C.TABLE_NAME) + '
WHERE ' +
QUOTENAME(C.COLUMN_NAME) + ' = ''' + cast(#guidToFind AS VARCHAR(50))+
''''
FROM
INFORMATION_SCHEMA.COLUMNS C
INNER JOIN INFORMATION_SCHEMA.TABLES T
ON C.TABLE_NAME = T.TABLE_NAME AND
T.TABLE_TYPE = 'BASE TABLE'
WHERE
C.DATA_TYPE = 'uniqueidentifier'
)
-- SELECT * FROM
EXEC( GuidCols.Query )
The problem is not solve if I uncomment the SELECT statement after CTE.
The purpose of this query is to find all instances of a GUID in a database. Currently I'm solving this problem using a script like this. However I would be happier to solve this problem without iterating through rows, using set operations and other techniques.
You can not use exec as a part of a CTE.
From WITH common_table_expression (Transact-SQL)
A CTE must be followed by a single SELECT, INSERT, UPDATE, or DELETE
statement that references some or all the CTE columns.
What you can do instead is to store the result from your query in a temp table, loop over the rows and execute one statement at a time.
The EXEC() function is available from T-SQL, but it is not accessible from within a SQL statement. I would assume this is the case because SQL is executed in several steps... something like:
Your statement is parsed.
An execution plan is generated.
The execution plan is run against the database and results are returned.
The EXEC() function is designed to dynamically execute a statement, so in order to do what you're asking, SQL Server would have to perform the first two steps, then while executing the statement, it would have to return back to the first step to parse/execute the dynamic statement. This would have to be repeated for each row in your results.
I assume this type of 'feature' is not available because it could adversely affect the performance and complexity of the db engine; so they leave it to us to execute the first statement, then loop through each record to execute the dynamic statements individually.
Exec executes a T-SQL command that you embed in its parentheses. The difference is that the EXEC() function can execute a string or string variable, as you saw in the preceiding code. The argument for EXEC() can be a literal string, but the real power of EXEC() comes to light when you use a variable.
It executes the command contained in the variable, but in a different context from the session calling the function. That's important, because it introduces some severe constraints. Any tables you create are visible to the EXEC() context, but variables declared by the calling session aren't visible to the EXEC() context, and vice versa.
I found an interesting article related to this at : http://msdn.microsoft.com/en-us/library/aa175921(v=sql.80).aspx
Although above is self sufficient, you can also go through : http://blog.sqlauthority.com/2007/09/13/sql-server-difference-between-exec-and-execute-vs-exec-use-execexecute-for-sp-always/
You may use OPENQUERY instead of EXEC:
SELECT * FROM OPENQUERY (OracleSvr, 'SELECT name FROM joe.titles WHERE name = ''NewTitle''');
Reference: https://learn.microsoft.com/en-us/sql/t-sql/functions/openquery-transact-sql?view=sql-server-2017