Getting Oracle stored procedure parameters - sql-server

I have a query in a SQL Server database that gets stored procedures parameters like this:
SELECT
parameter.name,
types.name,
types.is_nullable
FROM
sys.parameters AS parameter
INNER JOIN
sys.procedures AS procedures ON parameter.object_id = procedures.object_id
INNER JOIN
sys.types AS types ON parameter.system_type_id = types.system_type_id
AND parameter.user_type_id = types.user_type_id
WHERE
procedures.name = 'UsernameSP'
This returns a result set:
name name is_nullable
--------------------------------------
#Username nvarchar 1
#CreateDate datetime 1
I need this query for an Oracle database. How can I run this query in Oracle?

select argument_name,position, data_type
from user_arguments
where object_name = <your procedure>
order by position
That assumed you are logged in to the current schema where the procedure resides. I don't think oracle has an equivalent of "is_nullable"

Related

Check if stored procedure modifies table data in SQL Server

I am granting a user group permissions to execute all stored procedures in a database which contain the word "Report" or "PDF", on the condition that the execution of these stored procedures will not modify the data in the database.
Now, I am currently reading through each of these stored procedures one at a time and basically doing a code review on each of them with the intention of determining if they modify data, or if they simply retrieve data.
Is there a programmatic way to test for the modification of the database in a single-run procedure that only gets run when the programmers want it run?
You can get this information from the sys.dm_sql_referenced_entities system function. is_updated will be 1 when any table is inserted, updated or deleted.
SELECT
schema_name = s.name,
p.name,
is_updated = CAST(
CASE WHEN EXISTS (SELECT 1
FROM sys.dm_sql_referenced_entities(QUOTENAME(s.name) + '.' + QUOTENAME(p.name), 'OBJECT') r
WHERE r.is_updated = 1)
THEN 1 ELSE 0 END
AS bit)
FROM sys.procedures p
JOIN sys.schemas s ON s.schema_id = p.schema_id
WHERE (p.name LIKE '%Report%' OR p.name LIKE '%PDF%')
AND p.is_ms_shipped = 0;
db<>fiddle
You can look for words like INSERT, UPDATE,DELETE... in the stored procedure code, here's an exmple of the query :
SELECT *
FROM sys.procedures
WHERE OBJECT_DEFINITION(OBJECT_ID) LIKE '%INSERT%'
OR OBJECT_DEFINITION(OBJECT_ID) LIKE '%UPDATE%'

Using SQL Profiler to get the name of stored procedures

I have a database (SQL server 2000) with almost a thousand of stored procedures and I want to know which stored procedure is called after a button is clicked.
I try to use SQL Profiler (version 8.0) to capture the name of the stored procedure, but it seems it's not possible to get the name directly from SQL Profiler.
A tutorial says I can get the stored procedure name by running:
Select name from sysobjects where id = <ObjectID>
I tried but the id matched nothing.
How can I get the name of the stored procedure?
Thanks
This small query can give you a preview (the first 8000 characters) of your database T-SQL code (Procedures, Functions, Triggers, etc):
select o.id
,case
when parent_obj = 0
then ''
else '[' + Object_Name(parent_obj) + '].'
end + o.Name as Name
,c.text
,xType as Type
from syscomments c
join sysobjects o on (o.id = c.id)
where ColId = 1
and Category = 0
order by o.xType
,name
,c.Colid

Executing stored procedure in select query

I'm using SQL Server 2008 R2 and I am trying to run a query where a stored procedure will also be executed.
The query is:
select a.custnmbr, a.custname, a.salsterr, b.itemnmbr, b.itemdesc, d.slprsnid ,exec dbo.QtySoldPerMonth a.custnmbr, b.itemnmbr, #year
from rm00101_temp a, iv00101_temp b
inner join sop30300_RPT c on b.itemnmbr = c.itemnmbr
inner join sop30200_RPT d on c.sopnumbe = d.sopnumbe
where
b.itemnmbr like #houseCode + '%' and itmclscd like #classCode + '%'
AND DATEPART(year, d.docdate) = #year
group by a.custnmbr, a.custname, a.salsterr, b.itemnmbr, b.itemdesc, d.slprsnid
order by d.slprsnid, b.itemnmbr
What I'm really asking is how do I go about including the execution of the dbo.QtySoldPerMonth stored procedure in the select query? Also, the parameters for the stored procedures are: #custNo = a.custnmbr, #itemNo = b.itemnmbr and #year = #year.
Any help on how to rewrite the query to execute the sp will be appreciated.
create temp table for sp output
exec stored proc into temp table
join temp table to the rest of your query
create table #temp(yourCol1 int, your Col2 int...);
insert #temp(yourCol1,yourCol1...)
exec dbo.QtySoldPerMonth
select * from blah
join #temp t on (blah.blah=t.id...)
You can't execute a stored procedure as part of another query.
See if you can use a view of UDF to represent the same structure that the SP would return.
Edit
Another option: execute the stored procedure first and use the results in your main query.
You can't incorporate SP results to query, but you can dump SP to a table. Example:
http://blog.sqlauthority.com/2009/09/23/sql-server-insert-values-of-stored-procedure-in-table-use-table-valued-function/
But in your case it's not an option, as you want SP result with different parameters for every row; unless you modify SP so it returns a result set that you can later use after inserting it into table.

SQL Server 2005: SELECT default value of columns

I'm writing a script that analyses database tables and I'm having problems with fetching the default value of columns from SQL Server 2005.
The following works fine on SQL Server 2008, but when I run the same thing on SQL Server 2005, the result is an empty string, and I can't figure out why.
DECLARE #sDatabase VARCHAR(100);
DECLARE #sTable VARCHAR(100);
DECLARE #sColumn VARCHAR(100);
SET #sDatabase = 'SomeDatabase';
SET #sTable = 'tbl_something';
SET #sColumn = 'SomethingID';
SELECT
syscolumns.name AS column_name,
systypes.name column_type,
syscolumns.length AS column_length,
syscolumns.prec AS column_precision,
syscolumns.scale AS column_scale,
syscolumns.isnullable AS column_nullable,
syscomments.text AS column_default_value -- Should be default value!
FROM
sysobjects
INNER JOIN syscolumns ON sysobjects.id = syscolumns.id
INNER JOIN systypes ON syscolumns.xtype = systypes.xtype
LEFT OUTER JOIN syscomments ON syscomments.id = syscolumns.cdefault
WHERE sysobjects.xtype = 'U'
AND sysobjects.name = #sTable
AND systypes.name != 'sysname'
ORDER BY
sysobjects.name,
syscolumns.colid
Another version is as follows, but it's the same story; returns an empty string on SQL Server 2005, but the correct value on SQL Server 2008.
SELECT COLUMN_DEFAULT
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_CATALOG = #sDatabase
AND TABLE_NAME = #sTable
AND COLUMN_NAME = #sColumn
This is used for comparing certain changes between databases. Originally I thought that the problem was because SQL Server 2005 returned default values such as "((0))" while SQL Server 2008 was returning "(0)" for the same default value of the integer 0. That's what SQL Server Management Studio reports respectively. But upon further investigation, it turns out that the default values of SQL Server 2005 are simply not being displayed at all, so it is always recorded as a change when in fact there is none.
Any help deeply appreciated.
Thanks!
Have you tried the sys.default_constraints view?
This snippet finds the default for table TestTable column nr:
create table TestTable (nr float default 3.13)
select definition
from sys.default_constraints dc
join sys.columns c
on c.object_id = dc.parent_object_id
and c.column_id = dc.parent_column_id
where parent_object_id = object_id('TestTable')
and c.name = 'nr'

OBJECT_ID of object in another database - how to find database ID or name/fully qualified object name?

Example:
USE AnotherDB
-- This works - same ID as from other DB
SELECT OBJECT_ID('AnotherDB.ASchema.ATable')
-- This works
SELECT OBJECT_NAME(OBJECT_ID('AnotherDB.ASchema.ATable'))
USE ThisDB
-- This works - same ID as from other DB
SELECT OBJECT_ID('AnotherDB.ASchema.ATable')
-- Gives NULL
SELECT OBJECT_NAME(OBJECT_ID('AnotherDB.ASchema.ATable'))
Obviously the metadata functions expect a current database. The BOL entries typically have language like this for functions like OBJECT_NAME etc.:
The Microsoft SQL Server 2005 Database
Engine assumes that object_id is in
the context of the current database. A
query that references an object_id in
another database returns NULL or
incorrect results.
The reasons I need to be able to do this:
I can't USE the other database from within an SP
I can't create a proxy UDF stub (or alter anything) in the other databases or in master (or any other database besides my own) to help me out.
So how can I get the database from OBJECT_ID('AnotherDB.ASchema.ATable') when I'm in ThisDB?
My goal is to take a possibly partially qualified name from a configuration table, resolving it in the current context to a fully qualified name, use PARSENAME to get the database name and then dynamic SQL to build a script to be able to get to the meta data tables directly with database.sys.* or USE db; sys.*
You should be able to do this:
SELECT
name
FROM
AnotherDB.sys.objects --changes context
WHERE
object_id = OBJECT_ID('AnotherDB.ASchema.ATable')
This is what you effectively do with OBJECT_ID('AnotherDB.ASchema.ATable')
This means that you could rely on dbname.sys.objects and avoid confusion with metadata functions.
Note: the new Catalog views are designed to be used and not change from version to version, as per the link. In the old days, it was consider bad practice to use system tables but the stigma still remains.
So, you can safely rely on sys.objects rather that the metadata functions.
Do I understand it correctly that you want the db id of AnotherDB?
SELECT *
FROM master..sysdatabases
WHERE name = 'AnotherDB'
Otherwise, you can USE other db's in dynamic SQL if it helps:
DECLARE #SQL NVARCHAR(MAX)
, #objId INT
SET #SQL = N'
USE AnotherDB
SELECT #id = OBJECT_ID(''customer'')
'
EXEC SP_EXECUTESQL #SQL
, N'#id INT OUTPUT'
, #id = #objId OUTPUT
SELECT #objId
OR Execute SP's in other dbs with:
EXEC AnotherDB.dbo.ProcedureName
#paramX = ...
, #paramY = ...
Take a look at the PARSENAME function in TSQL - will allow you to pull out any of the 4-part portions of a fully (or non-fully) qualified name. For the database in your example:
select parsename('AnotherDB.ASchema.ATable',3)
returns:
AnotherDB
select parsename('AnotherDB.ASchema.ATable',2)
returns:
ASchema
If non-fully qualified, you'll get null results if you ask for the portion of a name that isn't included in the string:
select parsename('ASchema.ATable',3)
returns:
NULL
I had the same issue but with OJBECT_SCHEMA_NAME as well. Following on from chadhoc's response using parsename works with OBJECT_NAME like:
DECLARE #OrigTableName NVARCHAR(MAX);
SELECT #OrigTableName = 'AnotherDB.ASchema.ATable'
SELECT OBJECT_NAME(OBJECT_ID(#OrigTableName), DB_ID(PARSENAME(#OrigTableName, 3)))
, OBJECT_SCHEMA_NAME(OBJECT_ID(#OrigTableName), DB_ID(PARSENAME(#OrigTableName, 3)))
I used the following solution:
DECLARE #SchemaName varchar(255) = 'SchemaName'
DECLARE #ObjectName varchar(255) = 'ObjectName'
SELECT o.*
FROM AnotherDB.sys.objects AS o
INNER JOIN AnotherDB.sys.schemas AS s ON o.schema_id = s.schema_id
WHERE s.name = #SchemaName
AND o.name = #ObjectName
IF NOT EXISTS (
SELECT si.name
FROM <DatabaseName>.sys.indexes si
INNER JOIN <DatabaseName>.sys.objects so
ON si.object_id = so.object_id
WHERE si.name = '<IndexName>'
AND so.name = '<TableName>'
)
BEGIN
CREATE INDEX [<IndexName>] ON [<DatabaseName>].[<Schema>].[<TableName>]
([column1])
INCLUDE ([<column2>],,,,
)
WITH (online = ON)
END

Resources