C# how to Parse stored procedure String - c#

I have a Query string from client application. It comes with all parameters like
string query="PROCS.DBO.APP_2370_ANALYST_S 'ABC' , 'TESTDATA' , 100";
In Server, I made a function(Util.getParametersFromString) to parse string from client application to make parameter object Array using string.Split function.
I used ',' and ' ' as separator to make object array.
And I execute db procedure by using below code
object[] parameters = Util.getParametersFromString(query);
DbCommand cmd = dbconnection.GetStoredProcCommand("PROCS.DBO.APP_2370_ANALYST_S", parameters);
I works well if parameter string doesn't contain comma or single quotation mark.
If one of parameter string have one or more comma or single quotaion mark.
Like below
string query="PROCS.DBO.APP_2370_ANALYST_S 'A,B,C' , 'Hi, Sam 'The Legend' Brown was here ' , 100";
parameter array didn't come correctly. I didn't know how to parse string correctly in this
situation. Please give me advice to solve this problem
I am not good at english. So I am so sorry If I didn't write my question correctly
Regards,
Park

You can escape the single quotes - ' becomes '':
string query="PROCS.DBO.APP_2370_ANALYST_S 'A,B,C' , 'Hi, Sam ''The Legend'' Brown was here ' , 100";
As for the problem with a comma - it depends on how your function is written. You will have to escape the comma and make sure your function is aware of this escape sequence.

If both parameters of your query string are as flexible as your example, and you cannot change the way this string is generated as suggested in Oded's answer, you have a problem.
The query "PROCS.DBO.APP_2370_ANALYST_S 'ABC' , 'ABC' , 'ABC' , 100" for example, could be interpreted as having the first parameter "'ABC' , 'ABC'" and second parameter "ABC" or vice versa.
If, on the other hand, your first parameter may not contain 's, then you could identify the first parameter by looking between the first two 's, and the second parameter by falling between the third and the last '.

Related

How to get rid of single quotes in {0} string parameter?

I made a service and it retrieve sql command from physical xml file.
It looks like:
<Sql>
<![CDATA[
SELECT
MAX(COMM_HIST_NO) AS COMM_HIST_NO
, MAX(COMMUTER_NO) AS COMMUTER_NO
, MAX(ARRIVED_AT_WORK) AS ARRIVED_AT_WORK
, MAX(LEFT_WORK) AS LEFT_WORK
FROM COMMUTE_HISTORY
WHERE COMMUTER_NO = {0}
AND DATEDIFF(DAY, {1}, GETDATE()) = 0
]]>
</Sql>
And here's what returns sql command as a string:
// arParams is an Array.
string.Format(xmlDoc.SelectSingleNode("/SVC/Sql").InnerText,arParms)
{1} is going to be a column name and I want my {1} parameter to be written as column name, which has no single quotes.
To be specific, Mybatis in Java provides ${param} and #{param} and the latter one gets rid of single quotes from the string param.
.NET must have developed this feature!
Sorry, that was a simple mistake.
It worked at the first place. If single quotes are not given around the parameter, '' will not be there.

Regex to replace part of a query string with literals

I have a slight problem in that I am passing several SQL Server Like queries (which I don't have control over) in my .Net application and I need to escape some of the characters to make them literals for the database.
For example, suppose the field I am trying to query looks something like:
This_is [a] long_text field with [literal] characters in it
And my query looks something like this:
SELECT * FROM [MyTable] where [MyField] Like 'This_% [literal]%'
Now, this should get that data, the challenge is that the _ and [ characters are not seen by SQL Server as the literal characters, so I have to update my query to:
SELECT * FROM [MyTable] where [MyField] Like 'This[_]% [[]literal]%'
And then it works.
So, my question is that I would like to write a VB.Net function that uses RegEx to find the Like part of the statement and then to replace the characters.
Something along the lines of:
Public Function ConvertQuery(strSQL as string)
... Some kind of Regex that searches for the word "Like"
and then takes everytihng between the 2 "'" characters
Then replaces the "_" with "[_]" and "[" with "[[]"
Return ChangedString
End Function
I know I am giving REALLY bad details, I know what i want, I just can't figure out how to do it with RegEx.
ALSO, if there is a smarter way to do this with SQL Server Like statments, please also let me know!!!
Thanks!!
Seeing that C# tag, I assume you are OK with an answer in C#.
string input = "This_is [a] long_text field with [literal] characters in it";
var output = Regex.Replace(input, #"[_\[]","[$0]");
EDIT
string input = "SELECT * FROM [MyTable] where [MyField] Like 'This_% [literal]'";
var output = Regex.Replace(input, #"(?<=Like[ ]*\'.+?)[_\[]", "[$0]");

C# with MySql and Unicode characters

My problem is when using C# and MySQL database to save some records by sending parameters.
Although i have already set the charset as Utf-8 and i can see the unicode characters correctly, the problem i get when trying to insert unicode characters is that it only saves half of the string.
The really weird this is that this happens only with unicode strings such as Greek words and only when i send the query with parameters.
Ie. if my query as seen in C# is:
string query = "INSERT INTO tablename VALUES (NULL, #somestring)";
and i set the #somestring parameters value as "TESTING". This would work just fine.
If i try to set the value as unicode string "ΤΕΣΤΙΝΓ", the query executes fine with no errors but only saves half the characters in the database, ie. it only saves "ΤΕΣΤ".
On the other hand if i remove the parameters and adjust the query to be as:
string somestring = "ΤΕΣΤΙΝΓ";
string query = "INSERT INTO tablename VALUES (NULL,'" + somestring + "')";
the query again works just fine AND saves the whole word/sentence in the database.
Hope i explained it correctly and you can understand my situation.
Thanks
The length of how you declare the parameter #somestring is too short in c#.
UTF-8 takes upto 3 bytes per character so you'd need length to be 21 not 7 for example to fit testing and varieties thereof
Saying that, I've not used c# to call MySQL (only SQL Server) but I'm sure this is the problem

Multiline string literal in C#

Is there an easy way to create a multiline string literal in C#?
Here's what I have now:
string query = "SELECT foo, bar"
+ " FROM table"
+ " WHERE id = 42";
I know PHP has
<<<BLOCK
BLOCK;
Does C# have something similar?
You can use the # symbol in front of a string to form a verbatim string literal:
string query = #"SELECT foo, bar
FROM table
WHERE id = 42";
You also do not have to escape special characters when you use this method, except for double quotes as shown in Jon Skeet's answer.
It's called a verbatim string literal in C#, and it's just a matter of putting # before the literal. Not only does this allow multiple lines, but it also turns off escaping. So for example you can do:
string query = #"SELECT foo, bar
FROM table
WHERE name = 'a\b'";
This includes the line breaks (using whatever line break your source has them as) into the string, however. For SQL, that's not only harmless but probably improves the readability anywhere you see the string - but in other places it may not be required, in which case you'd either need to not use a multi-line verbatim string literal to start with, or remove them from the resulting string.
The only bit of escaping is that if you want a double quote, you have to add an extra double quote symbol:
string quote = #"Jon said, ""This will work,"" - and it did!";
As a side-note, with C# 6.0 you can now combine interpolated strings with the verbatim string literal:
string camlCondition = $#"
<Where>
<Contains>
<FieldRef Name='Resource'/>
<Value Type='Text'>{(string)parameter}</Value>
</Contains>
</Where>";
The problem with using string literal I find is that it can make your code look a bit "weird" because in order to not get spaces in the string itself, it has to be completely left aligned:
var someString = #"The
quick
brown
fox...";
Yuck.
So the solution I like to use, which keeps everything nicely aligned with the rest of your code is:
var someString = String.Join(
Environment.NewLine,
"The",
"quick",
"brown",
"fox...");
And of course, if you just want to logically split up lines of an SQL statement like you are and don't actually need a new line, you can always just substitute Environment.NewLine for " ".
One other gotcha to watch for is the use of string literals in string.Format. In that case you need to escape curly braces/brackets '{' and '}'.
// this would give a format exception
string.Format(#"<script> function test(x)
{ return x * {0} } </script>", aMagicValue)
// this contrived example would work
string.Format(#"<script> function test(x)
{{ return x * {0} }} </script>", aMagicValue)
Why do people keep confusing strings with string literals? The accepted answer is a great answer to a different question; not to this one.
I know this is an old topic, but I came here with possibly the same question as the OP, and it is frustrating to see how people keep misreading it. Or maybe I am misreading it, I don't know.
Roughly speaking, a string is a region of computer memory that, during the execution of a program, contains a sequence of bytes that can be mapped to text characters. A string literal, on the other hand, is a piece of source code, not yet compiled, that represents the value used to initialize a string later on, during the execution of the program in which it appears.
In C#, the statement...
string query = "SELECT foo, bar"
+ " FROM table"
+ " WHERE id = 42";
... does not produce a three-line string but a one liner; the concatenation of three strings (each initialized from a different literal) none of which contains a new-line modifier.
What the OP seems to be asking -at least what I would be asking with those words- is not how to introduce, in the compiled string, line breaks that mimick those found in the source code, but how to break up for clarity a long, single line of text in the source code without introducing breaks in the compiled string. And without requiring an extended execution time, spent joining the multiple substrings coming from the source code. Like the trailing backslashes within a multiline string literal in javascript or C++.
Suggesting the use of verbatim strings, nevermind StringBuilders, String.Joins or even nested functions with string reversals and what not, makes me think that people are not really understanding the question. Or maybe I do not understand it.
As far as I know, C# does not (at least in the paleolithic version I am still using, from the previous decade) have a feature to cleanly produce multiline string literals that can be resolved during compilation rather than execution.
Maybe current versions do support it, but I thought I'd share the difference I perceive between strings and string literals.
UPDATE:
(From MeowCat2012's comment) You can. The "+" approach by OP is the best. According to spec the optimization is guaranteed: http://stackoverflow.com/a/288802/9399618
Add multiple lines : use #
string query = #"SELECT foo, bar
FROM table
WHERE id = 42";
Add String Values to the middle : use $
string text ="beer";
string query = $"SELECT foo {text} bar ";
Multiple line string Add Values to the middle: use $#
string text ="Customer";
string query = $#"SELECT foo, bar
FROM {text}Table
WHERE id = 42";
You can use # and "".
string sourse = #"{
""items"":[
{
""itemId"":0,
""name"":""item0""
},
{
""itemId"":1,
""name"":""item1""
}
]
}";
In C# 11 [2022], you will be able to use Raw String literals.
The use of Raw String Literals makes it easier to use " characters without having to write escape sequences.
Solution for OP:
string query1 = """
SELECT foo, bar
FROM table
WHERE id = 42
""";
string query2 = """
SELECT foo, bar
FROM table
WHERE id = 42
and name = 'zoo'
and type = 'oversized "jumbo" grand'
""";
More details about Raw String Literals
See the Raw String Literals GitHub Issue for full details; and Blog article C# 11 Preview Updates – Raw string literals, UTF-8 and more!
I haven't seen this, so I will post it here (if you are interested in passing a string you can do this as well.) The idea is that you can break the string up on multiple lines and add your own content (also on multiple lines) in any way you wish. Here "tableName" can be passed into the string.
private string createTableQuery = "";
void createTable(string tableName)
{
createTableQuery = #"CREATE TABLE IF NOT EXISTS
["+ tableName + #"] (
[ID] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
[Key] NVARCHAR(2048) NULL,
[Value] VARCHAR(2048) NULL
)";
}
Yes, you can split a string out onto multiple lines without introducing newlines into the actual string, but it aint pretty:
string s = $#"This string{
string.Empty} contains no newlines{
string.Empty} even though it is spread onto{
string.Empty} multiple lines.";
The trick is to introduce code that evaluates to empty, and that code may contain newlines without affecting the output. I adapted this approach from this answer to a similar question.
There is apparently some confusion as to what the question is, but there are two hints that what we want here is a string literal not containing any newline characters, whose definition spans multiple lines. (in the comments he says so, and "here's what I have" shows code that does not create a string with newlines in it)
This unit test shows the intent:
[TestMethod]
public void StringLiteralDoesNotContainSpaces()
{
string query = "hi"
+ "there";
Assert.AreEqual("hithere", query);
}
Change the above definition of query so that it is one string literal, instead of the concatenation of two string literals which may or may not be optimized into one by the compiler.
The C++ approach would be to end each line with a backslash, causing the newline character to be escaped and not appear in the output. Unfortunately, there is still then the issue that each line after the first must be left aligned in order to not add additional whitespace to the result.
There is only one option that does not rely on compiler optimizations that might not happen, which is to put your definition on one line. If you want to rely on compiler optimizations, the + you already have is great; you don't have to left-align the string, you don't get newlines in the result, and it's just one operation, no function calls, to expect optimization on.
If you don't want spaces/newlines, string addition seems to work:
var myString = String.Format(
"hello " +
"world" +
" i am {0}" +
" and I like {1}.",
animalType,
animalPreferenceType
);
// hello world i am a pony and I like other ponies.
You can run the above here if you like.
using System;
namespace Demo {
class Program {
static void Main(string[] args) {
string str = #"Welcome User,
Kindly wait for the image to
load";
Console.WriteLine(str);
}
}
}
Output
Welcome User,
Kindly wait for the image to
load

Possible to pass name/value as parameter into Windows Console Application?

Building one of my first console apps.
This console app will run some stored procedures I'm defining. I would like to be able to pass in parameter values via the command line.
Is there any way to pass in a name value pair? For example:
myConsoleApp.exe sproc_GetLastActives, #LastActiveDate - 11/20/2009
I know how to retreive the parameter values, but I'm noticing that the args[] are split if I put in a / or a ,. How can I pass in name value pair?
Thanks!
Do you want that in a single string? Try this:
myConsoleApp.exe "sproc_GetLastActives, #LastActiveDate - 11/20/2009"
(i.e. just add quotes)
Slashes and commas shouldn't affect things, but the command line parser splits on spaces unless you've quoted it.
There are several solutions to this problem the most common is to use '/' or '-' to prefix parameters and = to delimit them from their arguments for example
consoleapp.exe /spname=sproc_GetLastActives /LastActiveDate="11/20/2009"
in your code your code you can use String.Split(arg[i], new char[] {'='}) to bust up the individual parameters.
consoleapp.exe key1 val1 key2 val2
args[] gives your 4 items, pair them up in your code. :P
Similar to mykhaylo's response, why not pass in the values at one string:
consoleapp.exe sproc_name key1=value1 "key2=Value With Spaces" key3=value3
Then just test for the presence of the = sign and parse it to get your key/value pair.

Categories