Find Sybase stored procedure in db given a text string that appears in the proc - stored-procedures

How do I find a stored procedure in a Sybase database given a text string that appears somewhere in the proc? I want to see if any other proc in the db has similar logic to the one I'm looking at, and I think I have a pretty unique search string (literal)
Edit:
I'm using Sybase version 11.2

Two variations on Graeme's answer (So this also won't work on 11.2):
This lists the name of the sproc too, but will return multiple rows for each sproc if the text appears several times:
select object_name(id),* from syscomments
where texttype = 0 and text like '%whatever%'
This lists each sproc just once:
select distinct object_name(id) from syscomments
where texttype = 0 and text like '%whatever%'

In SQL Anywhere and Sybase IQ:
select * from SYS.SYSPROCEDURE where proc_defn like '%whatever%'
I'm not that familiar with ASE, but according to the docs (available from sybooks.sybase.com), it's something like:
select * from syscomments where texttype = 0 and text like '%whatever%'

Please remember, that text column in syscomments is varchar(255), so one big procedure can consist of many lines in syscomments, thus, the above selects will not find the procedure name if it has been splitted into 2 text rows in syscomments.
I suggest the following select, which will handle the above case:
declare #text varchar(100)
select #text = "%whatever%"
select distinct o.name object
from sysobjects o,
syscomments c
where o.id=c.id
and o.type='P'
and (c.text like #text
or exists(
select 1 from syscomments c2
where c.id=c2.id
and c.colid+1=c2.colid
and right(c.text,100)+ substring(c2.text, 1, 100) like #text
)
)
order by 1
-- kudos for this go to the creator of ASEisql

select * from sysobjects where
id in ( select distinct (id) from syscomments where text like '%SearchTerm%')
and xtype = 'P'

select distinct object_name(syscomments.id) 'SearchText', syscomments.id from syscomments ,sysobjects
where texttype = 0 and text like '%SearchText%' and syscomments.id=sysobjects.id and sysobjects.type='P'

Multiple rows are used to store text for database objects the value might be accross two rows. So the more accurate answer is:
select distinct object_name(sc1.id)
from syscomments sc1
left join syscomments sc2
on (sc2.id = sc1.id and
sc2.number = sc1.number and
sc2.colid2 = sc1.colid2 + ((sc1.colid + 1) / 32768) and
sc2.colid = (sc1.colid + 1) % 32768)
where
sc1.texttype = 0 and
sc2.texttype = 0 and
lower(sc1.text + sc2.text) like lower('%' || #textSearched || '%')

Related

An example of a Cursor & UPDATE statement in conjunction inside a procedure on Redshift

Would you please provide an an example for a Redshift procedure where you have used a cursor and an UPDATE statement in conjunction? Is that even feasible, I couldn't find an example. I'm looking for a simple template code to learn how to have these 2 together in a single procedure on Redshift.
Here is an example use case:
I have a table like this:
CREATE TABLE test_tbl
(
Contactid VARCHAR(500),
sfdc_OppId_01 VARCHAR(500),
sfdc_OppId_02 VARCHAR(500),
sfdc_OppId_03 VARCHAR(500),
sfdc_OppId_04 VARCHAR(500),
sfdc_OppId_05 VARCHAR(500),
sfdc_OppId_06 VARCHAR(500)
)
I want to update each sfdc_OppId_xx with the relative value from another table; sfdc_tbl. Here is what sfdc_tbl looks like:
sfdc_contactId
sfdc_Opp_Id
AA123hgt
999999
AA123hgt
888888
AA123hgt
777777
AA123hgt
432567
AA123hgt
098765
AA123hgt
112789
So as you see, there are duplicate sfdc_contactid in the sfdc_tbl. My final goal is to list all the sfdc_Opp_Id for given contactid horizontally in the test_tbl. I shall not have duplicate contactid in the test_tbl.
INSERT INTO test_tbl (Contactid)
SELECT sfdc_contactId
FROM sfdc_tbl
GROUP BY sfdc_contactId
And here is what I'm trying to do:
CREATE OR REPLACE PROCEDURE testing_procedure (results INOUT refcursor)
AS
$$
BEGIN
OPEN cursor_testing FOR
SELECT
Ops.sfdc_Opp.id,
ROW_NUMBER () OVER(PARTITION BY Ops.sfdc_contactId ORDER BY sfdc_Opp_Id ) RWN
FROM sfdc_tbl Ops
INNER JOIN test_tbl tbl
ON Ops.sfdc_contactId = tbl.contactid;
UPDATE test_tbl
SET sfdc_Opp_01 = CASE WHEN cursor_testing.RWN = 1 THEN cursor_testing.sfdc_Ops_id ELSE NULL END,
sfdc_Opp_02 = CASE WHEN cursor_testing.RWN = 2 THEN cursor_testing.sfdc_Ops_id ELSE NULL END,
sfdc_Opp_03 = CASE WHEN cursor_testing.RWN = 3 THEN cursor_testing.sfdc_Ops_id ELSE NULL END,
sfdc_Opp_04 = CASE WHEN cursor_testing.RWN = 4 THEN cursor_testing.sfdc_Ops_id ELSE NULL END,
sfdc_Opp_05 = CASE WHEN cursor_testing.RWN = 5 THEN cursor_testing.sfdc_Ops_id ELSE NULL END,
sfdc_Opp_06 = CASE WHEN cursor_testing.RWN = 6 THEN cursor_testing.sfdc_Ops_id ELSE NULL END
;
END;
$$
LANGUAGE plpgsql;
I keep getting an error
incorrect syntax at or near "cursor_testing"
I've answered a question with a similar solution. The SQL uses a cursor's data to INSERT into a table and this same path should work for UPDATE - How to join System tables or Information Schema tables with User defined tables in Redshift
That being said and looking at your code I really think you would be better off using a temp table rather than a cursor. The first thing to note is that a cursor is not a table. Your use pattern won't work AFAIK. You read a cursor row by row (or bunches) which is contrary to Redshift's columnar table storage. So you will need to loop on the rows from the cursor and perform N updates. This will be extremely slow! You would be querying columnar data, storing the results in a cursor as rows, reading these row one by one, and then performing a new query (UPDATE) for each row. Ick! Stay in "columnar land" and use a temp table.

Create dynamic SQL based on column names passed through a string

I need to find out rows that are present in table A and missing from table B (using LEFT JOIN) wherein table A and table B are two tables with same structure but within different schema.
But the query has to be constructed using Dynamic SQL and the columns that need to be used for performing JOIN are stored in a string. How to extract the column names from string and use them to dynamically construct below query :
Database is Azure SQL Server
eg :
DECLARE #ColNames NVARCHAR(150) = 'col1,col2'
Query to be constructed based on columns defined in ColNames :-
SELECT *
FROM Table A
Left Join
Table B
ON A.col1 = B.col1
AND A.col2 = B.col2
AND B.col1 IS NULL AND B.col2 IS NULL
If the number of columns in #ColNames is more then the SELECT statement needs to cater for all the column.
Without knowing the full context, try this:
DECLARE #ColNames NVARCHAR(150) = 'col1,col2'
DECLARE #JoinContion NVARCHAR(MAX) = ''
DECLARE #WhereCondition NVARCHAR(MAX) = ''
SELECT #JoinContion += CONCAT('[a].', QUOTENAME(Value), ' = ', '[b].', QUOTENAME(Value), (CASE WHEN LEAD(Value) OVER(ORDER BY Value) IS NOT NULL THEN ' AND ' ELSE '' END))
,#WhereCondition += CONCAT('[a].', QUOTENAME(Value), ' IS NULL', (CASE WHEN LEAD(Value) OVER(ORDER BY Value) IS NOT NULL THEN ' AND ' ELSE '' END))
FROM STRING_SPLIT(#ColNames,N',')
SELECT #JoinContion, #WhereCondition
String_Split: To split the input string into columns
Lead: to determine if we need the AND keyword when it's not the last row.
Be aware the NOT EXISTS is probably a better solution then LEFT JOIN

I have a stored procedure which returns Dynamic columns(using Pivot) I want to bind stored procedure with RDLC report

I want to create RDLC report ,but the problem is that Columns in a table returned by the stored procedure are Dynamic, means Columns can be increased or decrease depends on the condition.
I have Created procedure.
alter proc sp_GetEmpBranAndDesigWise(
#BranchId nvarchar(200),
#ZoneId nvarchar(200)
)
as
if 1=0 Begin
set FMTONLY OFF End
select b.BranchName,b.BranchCity,z.ZoneName,b.BranchID,d.DesigName
,Count(d.DesigName) as TotalCount
INTO #RepTablTemp
from Emp_File emp
INNER join Branch b on emp.BranchID=b.BranchID
left join ZoneFile z on z.ZoneID=b.ZoneID
INNER join SWHouse_Production.dbo.emp_DesigFile d on emp.DesigID=d.DesigID
where Convert(nvarchar(250), b.BranchID) like #BranchId
and Convert(nvarchar(250), b.ZoneID) like #ZoneId
group by b.BranchName,z.ZoneName,b.BranchCity,b.BranchID,d.DesigName
order by b.BranchName,z.ZoneName,d.DesigName
--select * from #RepTablTemp order by BranchName,DesigName
--select * from Emp_File where BranchID=1055
Begin
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT DISTINCT ',' + QUOTENAME(DesigName)
from #RepTablTemp
group by DesigName
--order by 1
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
print #cols
set #query = N'SELECT BranchName,ZoneName,BranchCity,' + ISNULL(#cols,'0') + N' from
(
select BranchName,ZoneName,BranchCity,TotalCount, DesigName
from #RepTablTemp
) x
pivot
(
max(TotalCount)
for DesigName in (' + #cols + N')
) p '
exec sp_executesql #query;
select 0 AS mycol1int
print #query
drop table #RepTablTemp
End
BranchName|ZoneName|BranchCity|Designation1|Designation2|Designation3
here Designations are dynamic and can be increased,i want this kind of result in RDLC
enter image description here
In attached file highlighted fields are Designations coming from Designation Table.
You can't do that. RDLC expects a fixed "object" for a table. You can pass a dynamic object, but this object must be match with the dataset provided to the table.
But you can use several tablix and show them or not (visibility condition) for an specific condition loaded by a parameter (for example, a kind of table do you want to see or hide).

Most Efficient Version of PLSQL Stored Procedure

I am writing a PL/SQL stored procedure which will be called from within a .NET application.
My stored procedure must return
the count of values in a table of part revisions, based on an input part number,
the name of the lowest revision level currently captured in this table for the input part number
the name of the revision level for a particular unit in the database associated with this part number and an input unit ID.
The unit's revision level name is captured within a separate table with no direct relationship to the part revision table.
Relevant data structure:
Table Part has columns:
Part_ID int PK
Part_Number varchar2(30)
Table Part_Revisions:
Revision_ID int PK
Revision_Name varchar2(100)
Revision_Level int
Part_ID int FK
Table Unit:
Unit_ID int PK
Part_ID int FK
Table Unit_Revision:
Unit_ID int PK
Revision_Name varchar2(100)
With that said, what is the most efficient way for me to query these three data elements into a ref cursor for output? I am considering the following option 1:
OPEN cursor o_Return_Cursor FOR
SELECT (SELECT COUNT (*)
FROM Part_Revisions pr
inner join PART pa on pa.part_id = pr.part_id
WHERE PA.PART_NO = :1 )
AS "Cnt_PN_Revisions",
(select pr1.Revision_Name from Part_Revisions pr1
inner join PART pa1 on pa1.part_id = pr1.part_id
WHERE PA.PART_NO = :1 and pr1.Revision_Level = 0)
AS "Input_Revison_Level",
(select ur.Revision_Name from Unit_Revision ur
WHERE ur.Unit_ID = :2) as "Unit_Revision"
FROM DUAL;
However, Toad's Explain Plan returns Cost:2 Cardinality: 1, which I suspect is due to me using DUAL in my main query. Comparing that to option 2:
select pr.Revision_Name, (select count(*)
from Part_Revisions pr1
where pr1.part_id = pr.part_id) as "Count",
(select ur.Revision_Name
from Unit_Revision ur
where ur.Unit_ID = :2) as "Unit_Revision"
from Part_Revisions pr
inner join PART pa on pa.part_id = pr.part_id
WHERE PA.PART_NO = :1 and pr.Revision_Level = 0
Essentially I don't really know how to compare the results from my execution plans, to chose the best design. I have also considered a version of option 1, where instead of joining twice to the Part table, I select the Part_ID into a local variable, and simply query the Part_Revisions table based on that value. However, this is not something I can use the Explain Plan to analyze.
Your description and select statements look different... I based the procedure on the SQL statements.
PROCEDURE the_proc
(
part_no_in IN NUMBER
, revision_level_in IN NUMBER
, unit_id_in IN NUMBER
, part_rev_count_out OUT NUMBER
, part_rev_name_out OUT VARCHAR2
, unit_rev_name_out OUT VARCHAR2
)
AS
BEGIN
SELECT COUNT(*)
INTO part_rev_count_out
FROM part pa
WHERE pa.part_no = part_no_in
AND EXISTS
(
SELECT 1
FROM part_revisions pr
WHERE pa.part_id = pr.part_id
);
SELECT pr1.revision_name
INTO part_rev_name_out
FROM part_revisions pr1
WHERE pr1.revision_level = revision_level_in
AND EXISTS
(
SELECT 1
FROM part pa1
WHERE pa1.part_id = pr1.part_id
AND pa.part_no = part_no_in
);
SELECT ur.revision_name
INTO unit_rev_name_out
FROM unit_revision ur
WHERE ur.unit_id = unit_id_in;
END the_proc;
It looks like you are obtaining scalar values. Rather than return a cursor, just return the values using clean sql statements. I have done this numerous times from .net, it works fine.
Procedure get_part_info(p_partnum in part.part_number%type
, ret_count out integer
, ret_revision_level out part_revisions.revision_level%type
, ret_revision_name out part_revisions.revision_name%type) as
begin
select count(*) into ret_count from ....;
select min(revision_level) into ret_revision_level from ...;
select revision_name in ret_revision_name...;
return;
end;

Sybase - Get names of procs calling a given proc

I am looking for a functionality in reverse to sp_depends. sp_depends gives names of objects that the current object is using.
I want to get info in a reverse manner i.e. what all objects(procs in my case) calls the given proc ?
Note
I am using Sybase 12.5
I hope it will help you:
declare #Proc varchar(30)
select #Proc='ProcName'
select sod.name
from sysobjects so
join sysdepends sd on sd.id = so.id
join sysobjects sod on sod.id = sd.depid
where so.name = #Proc
and sod.type = 'P'
Try this query, I fixed the query of the previous answer, It gets the stored procedure(s) than call(s) the given stored procedure:
declare #Proc varchar(30)
select #Proc='procedure name'
select so.name
from sysobjects so
join sysdepends sd on sd.id = so.id
join sysobjects sod on sod.id = sd.depid
where sod.name = #Proc
and sod.type = 'P';

Resources