How can I pass sp parameter with N prefix - c#

I want to pass a parameter to sp with N prefix to solve an issue with foreign languages characters recognized as ???, I can't put N#test, directly, tried different ways without luck.
I have aspx.cs code file where I call to an sp, I want to do something like the following:
DECLARE #test NVARCHAR = 'N"★ "'
create table test (abc nvarchar)
insert into test values (#test)
select * from test
the code above is just an example, I will pass value to the parameter from .NET, How can I do it?

You don't need N prefix. You can specify parameter type as SqlDbType.NVarChar along with size. .Net will take care of preserving text encoding.
var foo = new SqlParameter("#test ", SqlDbType.NVarChar, 30)

N prefix means that your string is in UNICODE.
When you declare your variable as NVARCHAR it is already UNICODE.
So you don't need this N lineral at the begin of your variable.

Related

Is there a difference re-writing the query without prefix N and without single quotes on query parametrized [duplicate]

I have seen prefix N in some insert T-SQL queries. Many people have used N before inserting the value in a table.
I searched, but I was not able to understand what is the purpose of including the N before inserting any strings into the table.
INSERT INTO Personnel.Employees
VALUES(N'29730', N'Philippe', N'Horsford', 20.05, 1),
What purpose does this 'N' prefix serve, and when should it be used?
It's declaring the string as nvarchar data type, rather than varchar
You may have seen Transact-SQL code that passes strings around using
an N prefix. This denotes that the subsequent string is in Unicode
(the N actually stands for National language character set). Which
means that you are passing an NCHAR, NVARCHAR or NTEXT value, as
opposed to CHAR, VARCHAR or TEXT.
To quote from Microsoft:
Prefix Unicode character string constants with the letter N. Without
the N prefix, the string is converted to the default code page of the
database. This default code page may not recognize certain characters.
If you want to know the difference between these two data types, see this SO post:
What is the difference between varchar and nvarchar?
Let me tell you an annoying thing that happened with the N' prefix - I wasn't able to fix it for two days.
My database collation is SQL_Latin1_General_CP1_CI_AS.
It has a table with a column called MyCol1. It is an Nvarchar
This query fails to match Exact Value That Exists.
SELECT TOP 1 * FROM myTable1 WHERE MyCol1 = 'ESKİ'
// 0 result
using prefix N'' fixes it
SELECT TOP 1 * FROM myTable1 WHERE MyCol1 = N'ESKİ'
// 1 result - found!!!!
Why? Because latin1_general doesn't have big dotted İ that's why it fails I suppose.
1. Performance:
Assume your where clause is like this:
WHERE NAME='JON'
If the NAME column is of any type other than nvarchar or nchar, then you should not specify the N prefix. However, if the NAME column is of type nvarchar or nchar, then if you do not specify the N prefix, then 'JON' is treated as non-unicode. This means the data type of NAME column and string 'JON' are different and so SQL Server implicitly converts one operand’s type to the other. If the SQL Server converts the literal’s type
to the column’s type then there is no issue, but if it does the other way then performance will get hurt because the column's index (if available) wont be used.
2. Character set:
If the column is of type nvarchar or nchar, then always use the prefix N while specifying the character string in the WHERE criteria/UPDATE/INSERT clause. If you do not do this and one of the characters in your string is unicode (like international characters - example - ā) then it will fail or suffer data corruption.
Assuming the value is nvarchar type for that only we are using N''

Using IN operator with Stored Procedure Parameter

I am building a website in ASP.NET 2.0, some description of the page I am working about:
ListView displaying a table (of posts) from my access db, and a ListBox with Multiple select mode used to filter rows (by forum name, value=forumId).
I am converting the ListBox selected values into a List, then running the following query.
Parameter:
OleDbParameter("#Q",list.ToString());
Procedure:
SELECT * FROM sp_feedbacks WHERE forumId IN ([#Q])
The problem is, well, it doesn't work. Even when I run it from MSACCESS 2007 with the string 1,4, "1","4" or "1,4" I get zero results. The query works when only one forum is selected. (In (1) for instance).
SOLUTION?
So I guess I could use WHERE with many OR's but I would really like to avoid this option.
Another solution is to convert the DataTable into list then filter it using LINQ, which seems very messy option.
Thanks in advance,
BBLN.
I see 2 problems here:
1) list.ToString() doesn't do what you expect. Try this:
List<int> foo = new List<int>();
foo.Add(1);
foo.Add(4);
string x = foo.ToString();
The value of "x" will be "System.Collections.Generic.List`1[System.Int32]" not "1,4"
To create a comma separated list, use string.Join().
2) OleDbParameter does not understand arrays or lists. You have to do something else. Let me explain:
Suppose that you successfully use string.Join() to create the parameter. The resulting SQL will be:
SELECT * FROM sp_feedbacks WHERE forumId IN ('1,4')
The OLEDB provider knows that strings must have quotation marks around them. This is to protect you from SQL injection attacks. But you didn't want to pass a string: you wanted to pass either an array, or a literal unchanged value to go into the SQL.
You aren't the first to ask this question, but I'm afraid OLEDB doesn't have a great solution. If it were me, I would discard OLEDB entirely and use dynamic SQL. However, a Google search for "parameterized SQL array" resulted in some very good solutions here on Stack Overflow:
WHERE IN (array of IDs)
Passing an array of parameters to a stored procedure
Good Luck! Post which approach you go with!
When you have:
col in ('1,4')
This tests that col is equal to the string '1,4'. It is not testing for the values individually.
One way to solve this is using like:
where ','&#Q&',' like '*,'&col&',*'
The idea is to add delimiters to each string. So, a value of "1" becomes ",1,"in the column. A value of "1,4" for #Q becomes ",1,4,". Now when you do the comparison, there is no danger that "1" will match "10".
Note (for those who do not know). The wildcard for like is * rather than the SQL standard %. However, this might differ depending on how you are connecting, so use the appropriate wildcard.
Passing such a condition to a query has always been a problem. To a stored procedure it is worse because you can't even adjust the query to suit. 2 options currently:
use a table valued parameter and pass in multiple values that way (a bit of a nuisance to be honest)
write a "split" multi-value function as either a UDF or via SQL/CLR and call that from the query
For the record, "dapper" makes this easy for raw commands (not sprocs) via:
int[] ids = ...
var list = conn.Query<Foo>(
"select * from Foo where Id in #ids",
new { ids } ).ToList();
It figures out how to turn that into parameters etc for you.
Just in case anyone is looking for an SQL Server Solution:
CREATE FUNCTION [dbo].[SplitString]
(
#Input NVARCHAR(MAX),
#Character CHAR(1)
)
RETURNS #Output TABLE (
Item NVARCHAR(1000)
)
AS BEGIN
DECLARE #StartIndex INT, #EndIndex INT
SET #StartIndex = 1
IF SUBSTRING(#Input, LEN(#Input) - 1, LEN(#Input)) <> #Character
BEGIN
SET #Input = #Input + #Character
END
WHILE CHARINDEX(#Character, #Input) > 0
BEGIN
SET #EndIndex = CHARINDEX(#Character, #Input)
INSERT INTO #Output(Item)
SELECT SUBSTRING(#Input, #StartIndex, #EndIndex - 1)
SET #Input = SUBSTRING(#Input, #EndIndex + 1, LEN(#Input))
END
RETURN
END
Giving an array of strings, I will convert it to a comma separated List of strings using the following code
var result = string.Join(",", arr);
Then I could pass the parameter as follows
Command.Parameters.AddWithValue("#Parameter", result);
The In Stored Procedure Definition, I would use the parameter from above as follows
select * from [dbo].[WhateverTable] where [WhateverColumn] in (dbo.splitString(#Parameter, ','))

Use NVARCHAR variables in ASP.NET without declaring their length

i have this query
SELECT COUNT(Email) FROM Blacklist WHERE (Email = #email OR (Email like '#%' AND #email like '%' + Email)) AND (CustomerId = #cid OR CustomerId = -1)
I want to see if the value in blacklist starts with a # and if it does i also want to check the parameter and se if it ends with the value in blacklist.
(Email like '#%' AND #email like '%' + Email)
This works in SqlManager if i declare the variables exaktly as they are in the table like this.
declare #email as nvarchar(200) = 'firstname.lastname#xyz.com'
declare #cid as integer = 2
SELECT COUNT(Email) FROM Blacklist WHERE (Email = #email OR (Email like '#%' AND #email like '%' + Email)) AND CustomerId = #cid
The value in blacklist is "#xyz.com"
If i remove the (200) part from nvarchar(200) it stop working.
So my question is how to solve this from .NET C# ?
db.AddParameter("#email", SqlDbType.NVarChar, email);
You don't say what "stop working" means, what happens? Do you get the wrong result, or an error? And why do you remove the length from the declaration?
If you do not declare a variable length for nvarchar it is 1 by default and so it would have the value N'f' in this case; I guess you get a count of zero instead of whatever number you expect? Note that nvarchar(200)is not "fixed length", it means "maximum 200 characters"; nchar(200) would indeed be fixed length.
In any case, it's not really clear what your problem is here: the string length is simply part of the variable declaration in TSQL and it isn't clear why you can't do exactly what you showed above. You could declare the variable as nvarchar(max) to avoid dealing with specific lengths, if that's your issue.
Whether or not this is useful for you probably depends on how you connect to the database (you mentioned C# but are you using ADO, LINQ or something else?).
EDIT: In C#, you may be looking for the size parameter for the SqlDatabase.AddParameter method, if db in your question is indeed an SqlDatabase.
The problem is (I work with Fredrik) that when the query is executed from C# code, it returns 0, ie not blacklisted. When executed from SQL Managment Studio, where the length of the parameter can (must) be specified, it returns 1, ie IS blacklisted.
Our guess was that the parameter need a specified size (the same as the database field. However, it seems to be working from Management Studio even if the parameter is declared as nvarchar(100).
The question remains, why does the query return 0 when executed from code?
I had the same issue as you, and after much trial-and-error/digging, I think I've figured it out.
I've made a SQL Fiddle to demonstrate this issue: http://sqlfiddle.com/#!3/c0a51/3
Basically, even though you can set an NVARCHAR to strings of any length, it only saves off as many characters as it is defined to have. Since the default is a length of 1, the only character included for your LIKE statement is the first one, in your case, the first character in the email address.
Which is basically what Marc_S said, but with an explanation of why x = 'ab' was only giving us 'a'.
UPDATE
With more digging, I found that this is true of what happens if you write your SQL out like I did in the Fiddle. However, .NET will correctly infer the length of an NVARCHAR from the length of your string and declare the variable appropriately, so it won't have this problem: http://msdn.microsoft.com/en-us/library/hex23w80. So your query in studio is not behaving how your application is behaving.

Modify Stored procedure parameter value

My Stored procedure takes one parameter #IDs and it has values in it like '1,2,3'. I want to get rid of these single quotes. How can I do it? Like I want just 1,2,3 and NOT '1,2,3'. How do I modify this parameter value inside my SP?
you can do this:
#IDs = REPLACE(#IDs, '''', '');
If your parameter is VARCHAR, NVARCHAR or something like string :)
You could use a table varaible instead, read in BOoks online for how to do that.

Avoid entering double quotes from start & ending of a string

In a database, I have a string that contains "default" written in it. I just want to replace that default with 0. I have something like:
select * from tblname where test = 'default'
I do not want quotes in the replacement for "default".
I want
select * from tblname where test = 0
is there any way to do this?
I'm assuming the field test is of a text type (varchar, char, or the like).
First: Update the table to contain '0' where it contains 'default'.
UPDATE tblname SET test = '0' WHERE test = 'default'
Then: Select all rows with '0' in them. You can't leave off the quotes, because they are part of the SQL syntax.
SELECT * FROM tblname WHERE test = '0'
To be able to leave off the quotes, you must turn the field into a numeric one (int, float or the like).
I think you would be better using format strings
string myVar = "0";
string sql = String.Format(#"select * from tblname where test = \"{0}\"", myVar);
You should also ask yourself why you are generating inline SQL on the fly and not using stored procedures as this is how SQL injection attacks can occur unless you sanitize the input.
There are a number of things you can do in order to effect a simple string replacement;, however, I strongly suggest that you look into parameterization, to provide both injection safety and query-plan re-use.
Parameters also benefit by avoiding the quote issue - so just replace 'default' with (for example) #p1 and you're sorted. This replace can be:
-- TSQL
REPLACE(#cmd, '''default''', '#p1')
or
// C#
.Replace(#"'default'", #"#p1")
From C#, this would a DbCommand with parameters; from T-SQL you might consider sp_ExecuteSQL. Either way, you'd want to end up with:
select * from tblname where test = #p1
And supply #p1 as the parameter. So from C#:
DbParameter param = cmd.CreateParameter();
param.Value = 0; // etc
cmd.Parameters.Add(param);
Or from TSQL:
EXEC sp_ExecuteSQL #cmd, N'#p1 varchar(50)', 0
(replace varchar(50) with the correct type)

Categories

Resources