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!
Related
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.
I'm using SQL Server 2012, and I have a stored procedure with more than 25 parameters, which I need to call from C#. In my experience, having this many parameters can cause headaches when things go wrong, trying to identify which parameter is wrong/missing/whatever.
I've used Oracle in the past, which has the concept of user Defined Types, so it is possible to create a Type, which contains the 25 parameters, and pass this in instead. Now we have just one parameter.
What's the equivalent of this in SQL Server? I've read about Table Value parameters, and it seems obvious that this is what I should use, but I'm wondering if this is overkill for what would only ever have one row (i.e. one set of parameters). Every example I've seen describes how to use these to pass in multiple rows, so I'm wondering if there's a simpler way that I've missed.
Can I force the procedure to use array of parameters?
Something similar to Console.WriteLine(String msg, params[]) in C#
I need it to pass column names of table in procedure, something similar to INSERT INTO operation, but need to pass n arguments
As said above, a Table Valued Parameter is probably your best option here.
I've also had some success with XML parameters (might be easier to generate from C#, depending on the host), and allows some more complexity on the parameter side.
Before SQL 2008, I used pipe (|) separated strings and a string splitter function, which also work fine.
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
I have created a Web Service to send in a bunch of information to a PL/SQL procedure, however one of them is a array. What type do I use for this? I also want to put that array into a cursor after it comes in.
I don't have any experience with PL/SQL, so sorry if this doesn't apply. In MS SQL 2000/2005, there isn't a way to pass arrays into a procedure; I'm assuming PL/SQL has a similar limitation. The workaround I've used in the past is to pass in a delimited string (usually pipe delimited because commas were present in the data), and then have a function that can take a delimited string and break it up into a table result with one row per value. Then inside your procedure, you just call your split function passing it the delimited string and you have a table result that you can do whatever you want with (cursor over, join to other tables, etc).
EDIT: Just did a google for "PL/SQL table parameter" and had a few hits; Might be worth investigating to see if any of those results can help you.
This link might be of use. Or you can do what the other poster said and basically serialize your data into a string, pass it, and then unserialize it on the other end.