I'm dealing with some language issues in my SQL Server version 12.0.1800.
I have a table Persons and a stored procedure to return all persons based upon a like condition on their names. Name column is of type NVARCHAR(50).
The procedure works fine with the english languages, however when executing it with cyrillic characters, I need to use an N in front for results.
Does not work:
exec GET_PERSONS #argName = 'тест'
Works:
exec GET_PERSONS #argName = N'тест'
Problem is that I use this procedure from a C# client with entity framework 6. and there is no way to put an N in front of a parameter what I know, and according to sources I shouldn't need to if columns are nvarchar.
Call to procedure (returns nothing):
string name = "тест";
db.SP_GetPersons(name);
Procedure:
ALTER PROCEDURE [dbo].[GET_PERSONS]
#argName NVarchar(100)
AS
BEGIN
SELECT
name
FROM
Persons
WHERE
Name like ISNULL(#argName + '%', '%')
or Name like concat('% ', #argName, '%')
END
Related
I am trying to create a stored procedure that is getting values from a linked to our Sql Server DB2 server.In the stored procedure I have this query:
DECLARE #CarID nvarchar(10)
DECLARE #TSQL varchar(8000)
SET #CarID = '1111'
SELECT #TSQL = 'SELECT * FROM OPENQUERY(LINKEDSERVER,''SELECT * FROM TestTable WHERE Column LIKE ''''' + #CarID + '%' + ''''''')'
EXEC (#TSQL)
Everithing is working fine but when I add the stored procedure to the Entity model the signature of the procedure is:
GetUsers(string):int
But when I run the procedure returns data rows. How can I modify the procedure to return a data set not an integer?
EF handles a stored procedure somewhat similar as a scalar function. EF doesn't know how many datasets and which columns will be selected in your stored procedure, therefore cannot generate the classes.
Best way to select something on a linked server is with a view.
Simply create the view with the four part name and add it to your EF datamodel. Then EF will be able the generate the class.
CREATE VIEW [dbo].[vTestTable]
AS
Select * from [LINKEDSERVER].[DatabaseName].[Schema].[TestTable]
GO
Then in .NET
var result = db.vTestTable.Where(t=> t.Column.StartsWith(CarId)).ToList();
I have a functionality wherein the user types something in a textbox and at the back end a stored procedure is used with dynamic query for searching from a table which supports both English and Arabic languages.
It works fine with English words, but when I search with Arabic words it returns nothing. My stored procedure looks like:
ALTER PROCEDURE [dbo].[usp_SimilarItems_Search]
#Search NVARCHAR(1000) = NULL
, #Culture NVARCHAR(100) = NULL
AS
BEGIN
DECLARE #Query NVARCHAR(MAX) = ''
SET #Query = 'SELECT *
FROM Products
WHERE [Status] = 1
AND CultureID = dbo.udf_GetCurrentCultureID('''+#Culture+''') '
IF(ISNULL(#Search,'') <> '')
SET #Query = #Query +
' AND
(
ProductName like ''%'+#Search+'%''
OR ProductTitle like ''%'+#Search+'%''
OR Author like ''%'+#Search+'%''
OR Publication like ''%'+#Search+'%''
) '
EXEC (#Query)
END
I know for nvarchar values you have to prefix it with N. I have tried in the sql editor and it works fine, but how to do it from my C# method. I have also used
set #Search = N''+#Search+''
but it is printing '??????????'
To find out exact problem, try printing raw output on the page and also see what exactly is query returning in debug mode!
Seems like your control doesn't support language or your browser / windows needs installation of appropriate fonts, that should do.
If the question is understood properly then the answer can be found here
Select Query giving output as ??????????? with different language text
The catch is the moment I assigned an nvarchar variable with that Arabic text without the 'N' prefix it lost its Unicode property, so after that how much I try it cannot be changed. So the main idea is when you have such type of scenario better prefix it from the application side itself, when you are passing the parameters. In this way the moment the parameter is assigned with that value it accepts as a Unicode string. Hope I explained the point clearly.
So this works great:
select name from users where id = #id
However, that only selects 1 guy. Say I have 3 IDs instead, normally the SQL would look something like this (without using parameters)
select name from users where id in (4,6,9)
However, it doesn't seem to work when I write
select name from users where id in (#IDs)
and insert a list into #IDs, like this
cmd.Parameters.AddWithValue("#IDs", userIDs);
Is there any way to do what I'm trying to? It's important to note that the sql I'm calling is (and has to be) a stored procedure.
There are two ways to do this. The first is by passing a string to a stored procedure and then adding it to a dynamic query:
-- #IDs = '4,6,9'
DECLARE #MyQuery nvarchar(max)
SET #MyQuery = N'SELECT name FROM users WHERE id IN (' + #IDs + ')'
EXEC(#MyQuery)
On the other hand, if you are using SQL Server 2008 or later, you can use a table-valued parameter (this is my preference).
First, create a user-defined table type:
CREATE TYPE IDList AS TABLE (
id int
)
THEN, use the user defined type as the type for your parameter:
DECLARE #IDs IDList
INSERT INTO #IDs (ID) VALUES (4),(6),(9)
SELECT name FROM users u INNER JOIN #IDs i WHERE u.id = i.id
If you are using .NET to consume a stored procedure, you can find sample code for user-defined SQL types on MSDN.
You can create a dynamic SQL query inside your stored procedure:
DECLARE #SQLQuery AS NVARCHAR(500)
SET #SQLQuery = 'select name from users where id in ( ' + #userIDs + ')'
EXECUTE(#SQLQuery)
You'll have to be careful and sanitize the contents of #userIDs though to prevent SQL injection attacks.
On our side we are using iBatis.Net to manage this. Execute query sounds quite ugly but it still does the trick.
We were mostly using string split in SQL. See [question]How do I split a string so I can access item x?
I have SQL datatable StudetnMaster having FirstName nvarchar(100) and contains Data Entry Gujarati Language (Unicode Chracters)
Sample:
StudentId FirstName
1 ઘનશ્યામ
2 જીગર
Now I have following query for searching:
Select *
from StudetnMaster
where FirstName like N'" + textBox1.Text.Trim() + "%'
It's working fine but in stored procedure I have to pass parameter for FirstName as Follows:
ALTER PROCEDURE dbo.StoredProcedure1
#FirstName nvarchar(100)
AS
select *
from StudentNew
where FirstName like N#FirstName+'%'
But it throws an Error saying :
Invalid Column Name N#FirstName
How can I use 'N' in SP for parameter because without using N' Unicode Text is not searchable?
For inline query as mentioned above i got result, but for stored procedure I got error, so how can we use 'N' in SP?
Is there any other solution for searching unicode characters in SP?
Thanks
Just like in comment was written- you dont have to add N to parameter.
As you define parameter as nvarchar, it means- 2 bytes per symbol (that what N stands for, when you write N'string').
If that necessary, you can add collation there:
select * from StudentNew
where FirstName like #FirstName+'%' Collate YourCollationName
I want to use a query as following, I am looking for exact information/link to escape strings
BookTitle is NVARCHAR(200)
SELECT * FROM Books WHERE BookTitle IN ('Mars and Venus', 'Stack''s Overflow \r\n')
Question:
Does only "'" needs to be escaped or even \r\n needs to be escaped as well? MySql .Net Provider exposes a method to escape string values, is there any such function in Sql Server .Net Provider?
I probably need C# equivalent escaping for string values.
I am aware of Parameterized Command, but in order to minimize my server to client communication, and my values in IN clause are in number from 20 to 50, it becomes too much network expensive to run SELECTs for each value of BookTitle in one call. Rather running single query and returning all results cascaded helps saving network resources.
SQL Server won't recognise the \r\n sequence, whether it's escaped or not.
You'll need to do something like this instead if you want to match the \r\n in BookTitle:
-- \r = CHAR(13)
-- \n = CHAR(10)
SELECT *
FROM Books
WHERE BookTitle IN ('Mars and Venus', 'Stack''s Overflow ' + CHAR(13) + CHAR(10))
There are more things that have to be escaped than just quotes or new line characters. What if there's a binary input (by hacker)? Better use PreparedStatement (in java) or any other equivalent in the target language. Java sample:
PreparedStatement ps = con.prepareStatement("SELECT * FROM Books WHERE BookTitle IN (?, ?)");
ps.setString(1, "Mars and Venus");
ps.setString(2, "Stack's Overflow
and
");
ResultSet rs = ps.executeQuery();
....
I've run into a similar problem, where I needed to have a IN in my select query, and the number of elements varied at run time.
I use a parameterized query in the form of a stored procedure and pass in a delimited string containing the list of things I'm looking for. The escaping is automatically handled by the system, no need to take extraordinary steps. Better not make it delimited by characters that will be found in the text you're searching (like commas). a vertical bar ("|") would probably work best in many cases.
By the way, make sure the CRLFs in your table are CHAR(13)+CHAR(10) because the opposite way around isn't \r\n and you wouldn't find it if Environment.NewLine was part of your search.
Here's a stored procedure using a quick and dirty parse resolving to a table that I have used:
CREATE PROCEDURE FindBooks
(
#list varchar(500)
)
AS
CREATE TABLE #parse_table (item varchar(500))
DECLARE #temp VARCHAR(500)
DECLARE #result VARCHAR(500)
DECLARE #str VARCHAR(500)
DECLARE #pos SMALLINT
SET #temp = RTRIM(LTRIM(#list))
SET #pos = 1
WHILE #pos > 0
BEGIN
SET #pos = CHARINDEX('|',#temp)
IF #pos > 0
BEGIN
SET #result = SUBSTRING(#temp,1,#pos - 1)
SET #temp = RTRIM(LTRIM(SUBSTRING(#temp,#pos+1,LEN(#temp) - #pos)))
INSERT INTO #parse_table
SELECT #result
END
ELSE
INSERT INTO #parse_table
SELECT #temp
END
SELECT * FROM Books WHERE Title in (select * from #parse_table)
Simply create your list of book titles as a simple string (containing whatever embedded apostrophes, CRLFs, and so on) and use a parameterized query. Of course, your stored proc can contain other things besides the delimited list.
You could use table value parameters to pass in the the values for your IN statement. If you are not using a new enough version of visual studio and/or sql server to have access to table value parameters, you can instead pass in one comma separated list as string parameter, and then parse the the parameter into a table. There are several methods to split strings into a temp table/table variable. You can google "split function in sql server" for several options.
Usually what I'd do for situations like this, is pass your information in as a parameter, but in XML, so you can do something like this:
DECLARE #iDoc INT
EXEC sp_xml_preparedocument #iDoc OUTPUT, #MyXml
SELECT
*
FROM
MyTable
WHERE
MyColumn IN (SELECT [Id] FROM OPENXML(#iDoc,'/ss/s',2) WITH ([Id] INT '.'))
EXEC sp_xml_removedocument #iDoc
in this case, the xml would look like '<ss><s>1</s><s>2</s>...etc...</ss>'