Find Out List Of Objects Referenced In Snowflake Procedure - snowflake-cloud-data-platform

I want to get list of Objects referenced in Snowflake Procedure , let us say It is using Tables, Views Inside it , I want to find those items from Procedure definition , as currently there is no function in Snowflake that can provide this information.
GET_OBJECT_REFERENCES https://docs.snowflake.com/en/sql-reference/functions/get_object_references.html is function now only available for Views and not for Procedure.
Any pointers in scanning the definition of Procedure and figure out objects in it.

As Felipe pointed out, you can pass the name of a table or view as a parameter into the stored procedure. In that case there's no way to know what objects the SP will reference.
If your organization tends not to do that; if your SQL in stored procedures tends to be more along the lines of "select * from my_table" you can simply search for those references in the stored procedure code.
The following statement is crude, but effective. It could be developed and polished a lot, and it could miss references. It also only finds the first match, while a more useful query would return all and flatten out the array. I may have time to work on that a bit. It did find a lot in my test. It simply looks for the following pattern:
SQL Command ... Matching Clause for that Command ... Semicolon
The reason this works is that even if you don't terminate the SQL in the stored procedure, the JavaScript line should be terminated with a semicolon. JavaScript is comparatively forgiving of missing semicolons, but it should hit one eventually and match the SQL statement.
select PROCEDURE_CATALOG
,PROCEDURE_SCHEMA
,PROCEDURE_NAME
,ARGUMENT_SIGNATURE
,regexp_substr(PROCEDURE_DEFINITION, 'SELECT\\s.*FROM.*;|INSERT\\s.*INTO.*;|UPDATE\\s.*SET.*;|MERGE\\s.*INTO.*;|DELETE\\s.*FROM.*;|MERGE\\s.*USING.*;',1, 1, 'ims') STATEMENT
from MY_DATABASE.INFORMATION_SCHEMA.PROCEDURES
where STATEMENT is not null;
I write a lot of stored procedures, and to Felipe's point this returns a lot of rows like this for me:
select ${params.leftColumnList} from ${params.leftObject} order by ${leftTimestamp};`);
In those cases, you'd need to have someone who can read code figure out what it's referencing. In this case, the SP accepts parameters for those fields, so they could be any tables.

Related

How to list all jobs which operate with specified database object?

Is there a way to list in Sql Server all the jobs which operate on a mentioned Sql Server object, for example a certain table (directly or indirectly through a stored procedure for example)?
An example: I am interested in a certain table or view, so if there is a job which invokes (in any step) a procedure, which in its turn does any operation on that table/view (like insert or select or update etc), I'd like to see it listed.
Side note: sp_depends seems to list only the procedures and functions, but not the jobs.
There is no built-in way to find indirect dependencies. You can check which jobs directly call a certain stored procedure, but no way to see which tables or other objects get used by that stored procedure unless you check the direct dependencies of that stored procedure.
So if you are looking for a specific table, you can find objects that reference it directly, but not objects that reference THOSE objects (indirect dependency).
You would either have to write your own script or search around and see if someone else has written one.

How do i get list of Synonyms were used in the stored procedure

I think this is a rather valid question, and I'm not sure why it was marked for closure unless this is also a duplicate.
As Ben Thul points out in his comment:
One of the points of synonyms is to abstract the actual location of an
object so that you can change it in only one place (i.e. the synonym
definition) and anywhere the synonym is used automatically gets the
right location.
This is certainly an excellent reason for synonyms (if not THE reason) but consider a scenario where you have a large SQL codebase that you inherited as the sole manager. You manage the data tables, views and stored procedures and inside this database there are near-thousands of database objects.
One day, (oops!) an update on a data feed breaks an internal process. It is now your task to inspect any broken code and fix the issue. After a bit of searching, you find an INSERT reference in an SP that doesn't seem to point to a data table? Therefore, you assume it is a synonym and you now need to find the underlying table so that you can further inspect what may be broken.
This is a valid case and, in fact, is exactly where I am today. The original poster takes the logical need one step further than just asking for a list of database object synonyms. Instead, he asks if there is a way to list all synonyms used in one stored procedure?
Personally, I'd be fine with a list of all synonyms, however, answering his question does get one step closer to the end-need.
ORIGINAL QUESTION
Can some one please help me out, To get the list of Synonyms were used in the Stored procedure (Example: Procs.myproc)
I believe that you can not do that. The only thing you can do is to find all the name of synonyms and find these strings in stored procedure.
You can get all names of synonyms by following query:
SELECT
s.name,
COALESCE(PARSENAME(s.base_object_name,4),##servername) AS serverName,
COALESCE(PARSENAME(s.base_object_name,3),DB_NAME(DB_ID())) AS dbName,
COALESCE(PARSENAME(s.base_object_name,2),SCHEMA_NAME(SCHEMA_ID())) AS schemaName,
PARSENAME(s.base_object_name,1) AS objectName
FROM sys.synonyms s
ORDER BY 2,3,4,5
then you go 1 by 1 in loop and check the presence "objectName" in the stored procedure

combine several queries into one

I would like to be able to query multiple of the same type of argument (for example, several IDs, just to keep the example simple) so I only have to execute a procedure once instead of one time for each individual ID. Where my single-instance proc returns, say, a name, my get-all proc would return a single-column table of names.
What I have now:
EXEC MyProc(123);
EXEC MyProc(456);
EXEC MyProc(789);
What I would like:
// Square brackets aren't correct syntax,
// they just represent a list that contains x number of IDs
EXEC MyProc([123, 456, 789]);
Can I do this, and if so, is there an easy mechanism for handling such a thing that doesn't involve cursors and various over-complicated things? Would this even be considered a good idea?
To execute the proc only once, you'll have to refactor your proc to work with multiple IDs, as there is no T-SQL function or syntactic sugar to do this for you.
If this is to be varadic in that there may be one or many IDs, you'll have to pass multiple IDs to your proc in one parameter. This passing of an array of sorts can be easier in more recent versions of SQL Server.
For example, you can try passing:
TVPs in SQL Server 2008+
delimited strings that are then split in the proc
xml which is then parsed in the proc
a table name which is then read by the proc dynamically
use a table name which is known by both the proc and the caller beforehand
A quick search for passing arrays is SQL Server will yield more results, among the best of them is Arrays and Lists in SQL Server as mentioned by #Andomar.

Define a String constant in SQL Server?

Is it possible in SQL Server to define a String constant? I am rewriting some queries to use stored procedures and each has the same long string as part of an IN statement [a], [b], [c] etc.
It isn't expected to change, but could at some point in future. It is also a very long string (a few hundred characters) so if there is a way to define a global constant for this that would be much easier to work with.
If this is possible I would also be interested to know if it works in this scenario. I had tried to pass this String as a parameter, so I could control it from a single point within my application but the Stored Procedure didn't like it.
You can create a table with a single column and row and disallow writes on it.
Use that as you global string constant (or additional constants, if you wish).
You are asking for one thing (a string constant in MS SQL), but appear to maybe need something else. The reason I say this is because you have given a few hints at your ultimate objective, which appears to be using the same IN clause in multiple stored procedures.
The biggest clue is in the last sentence:
I had tried to pass this String as a
parameter, so I could control it from
a single point within my application
but the Stored Procedure didn't like
it.
Without details of your SQL scripts, I am going to attempt to use some psychic debugging techniques to see if I can get you to what I believe is your actual goal, and not necessarily your stated goal.
Given your Stored Procedure "didn't like that" when you tried to pass in a string as a parameter, I am guessing the composition of the string was simply a delimited list of values, something like "10293, 105968, 501940" or "Juice, Milk, Donuts" (pay no attention to the actual list values - the important part is the delimited list itself). And your SQL may have looked something like this (again, ignore the specific names and focus on the general concept):
SELECT Column1, Column2, Column3
FROM UnknownTable
WHERE Column1 IN (#parameterString);
If this approximately describes the path you tried to take, then you will need to reconsider your approach. Using a regular T-SQL statement, you will not be able to pass a string of parameter values to an IN clause - it just doesn't know what to do with them.
There are alternatives, however:
Dynamic SQL - you can build up the
whole SQL statement, parameters and
all, then execute that in the SQL
database. This probably is not what
you are trying to achieve, since you
are moving script to stored
procedures. But it is listed here
for completeness.
Table of values -
you can create a single-column table
that holds the specific values you
are interested in. Then your Stored
Procedure can simply use the column
from this table for the IN clause).
This way, there is no Dynamic SQL
required. Since you indicate that
the values are not likely to change,
you may just need to populate the
table once, and use it wherever
appropriate.
String Parsing to
derive the list of values - You can
pass the list of values as a string,
then implement code to parse the
list into a table structure on the
fly. An alternative form of this
technique is to pass an XML
structure containing the values, and
use MS SQL Server's XML
functionality to derive the table.
Define a table-value function that
returns the values to use - I have
not tried this one, so I may be
missing something, but you should be
able to define the values in a
table-value function (possibly using
a bunch of UNION statements or
something), and call that function
in the IN clause. Again - this is an
untested suggestion and would need
to be worked through to determine
it's feasibility.
I hope that helps (assuming I have guessed your underlying quandary).
For future reference, it would be extremely helpful if you could include SQL script showing
your table structure and stored procedure logic so we can see what you have actually attempted. This will considerably improve the effectiveness of the answers you receive. Thanks.
P.S. The link for String Parsing actually includes a large variety of techniques for passing arrays (i.e. lists) of information to Stored Procedures - it is a very good resource for this kind of thing.
In addition to string-constants tables as Oded suggests, I have used scalar functions to encapsulate some constants. That would be better for fewer constants, of course, but their use is simple.
Perhaps a combination - string constants table with a function that takes a key and returns the string. You could even use that for localization by having the function take a 'region' and combine that with a key to return a different string!

Stored procedure: Searching in a table when passing an array of values

I need to create a stored procedure which receives a parameter (named #codes).
This is a string which contains a list of codes separated by a semicolumn.
I'd need to look inside a table and return all rows that have a code (which is in the column EANcodes) which was passed in the #codes parameter.
Can anyone help me get started. My knowledge of stored procedures is very limited.
Thanks in advance.
Ideally, I'd prefer to see the parameter passed in another way, either using a table-value parameter (assuming SQL 2008) or XML which can be easily shredded into a table.
Alternatively, use a SQL split function (one example is here) to parse the string into a temp table, then join against that table in your select query.
Stored Procedures aren't really meant to handle a list of strings as a paramter. You'd be better off splitting it up in your App code and then calling the stored procedure many times with each one as a parameter.
However, if you feel the need to do it this way. You could loop through the string, and use CHARINDEX to find the next index of a semicolon and then use SUBSTRING to get the next code. Then you could use a CTE for the matching rows at each iteration and when the loop is done, simply return the CTE. This is pretty hacky, but I can't think of any other way to do this.
(Those are the T-SQL string functions)
For info on the string manipulation functions (in T-SQL): http://msdn.microsoft.com/en-us/library/ms186323.aspx
And here are similar functions in MySQL: http://dev.mysql.com/doc/refman/5.1/en/string-functions.html

Resources