Convert string to varbinary - Comparing the two - c#

I need to covert a string to a varbinary(85), which is the data type in my SQL Server Table (unable to change). The data is for a username and I need to compare the windows user name of a person who logs onto a website with this SQL data entry. An example of a login that I have in my database is:
0x0105000000000005150000004CCDD8292B55E7A8CD006C0E061F0012 which is the of the datatype varbinary(85).
Now I need to compare this to a string. What is the best way for me to convert a string to varbinary(85) so that I can get the exact same value.
I would preferably do this all in C# although I guess I could do it on the database end in SQL.
ANSWER:
using sql I could generate the name perfectly.
SELECT SUSER_SID(string)

1) I would create an [unique] index on varbinary(85) column:
CREATE UNIQUE INDEX IUN_Users_UserName
ON dbo.Users (UserName) -- Where UserName is varbinary(85)
2) I would convert current user name to varbinary(85) using the same algorithm
DECLARE #binCurrentUserName VARBINARY(85);
SET #binCurrentUserName = .... convert here the current user name to VB(85) ...
and I would compare only varbinary values:
SELECT u.UserID
FROM dbo.Users u
WHERE u.UserName = #binCurrentUserName -- Please remember that UserName's type is VB(85)
Note: converting the varbinary values from UserName column to string (nvarchar) it's a bad idea because the SQL query will look like this
SELECT u.UserID
FROM dbo.Users u
WHERE CONVERT(... u.UserName ... ) = #nvarcharCurrentUserName
and because will be a function (ex. CONVERT) applied on UserName column this will block Index Seek => the execution plan of this query will contain an Index Scan operator.

Related

PostgreSQL stored procedures

I'm new to PostgreSQL. I have a winforms app thats calling to a PostgreSQL db. Instead of passing in the query, id rather use PostgreSQL paramaterised stored procedures. I am able to all and get a return for a parameterless stored procedure but when I add parameters and execute the call, I get an error saying that coloumn userId doesn't exist.
userid is the parameter.
On PostgreSQL, when creating the sp, I also create an IN argument with that thats same rype and name.
What am I missing here?
The sql is a simple:
select * from public.users u where u.userid = userid.
use it to identify a parameter in SQL:
Select * from public.users u where u.userid = #userid
You indicated that you "create an IN argument with that thats same (t)ype and name". That is not quite what you do want to do. While you do want the type to be the same the name must either different or qualified by the function name. If it the same you will get all rows as the intended parameter name will be interpreted as the column name; basically resulting in:
Select * from table_name where column_name = column_name;
Which is true whenever the value isn't null. Now there are 2 approaches, using userid and assuming its unique:
create or replace function get_user(userid_in users.userid%type)
returns setof users
language sql
as $$
select *
from users where userid = userid_in ;
$$;
OR
create or replace function get_user(userid users.userid%type)
returns setof users
language sql
as $$
select *
from users where userid = get_user.userid ;
$$;

SQL search by multiple lists of values for multiple columns

I may have a slightly naive question, but I have never worked with databases before. I am a .NET engineer and I use Dapper to access the SQL Server database.
The situation is the following: I have a denormalized table for persisting several types of entities. Each has a composite key (type, id, owner_id) and each row of the key is of string type (but it's not important). And, let's say, I'm writing to the database many interests for different users (Bulk post). In order for them to not repeat, I need to make a query and determine which are already present in the database.
So, I have this code in my InterestService class:
private IEnumerable<Interest> GetAlreadyExistingInterestsFor(IEnumerable<Interest> interestsForCreating) =>
_interestRepository.GetInterests(interestsForCreating.Select(interest => interest.Id).ToList(),
interestsForCreating.Select(interest => interest.UserId).ToList());
After that I have some logic and so on. It's not important.
InterestRepository method GetInterests looks like this:
public GetInterests(IList<string> interestIds, IList<string> userIds)
{
var query = #"SELECT type, id, owner_id
FROM entities
WHERE type = 'interest'
AND id IN #InterestIds
AND owner_id IN #UserIds";
return _dbContext.ExecuteQuery(query, new { InterestIds = interestIds, UserIds = userIds });
}
The code may have mistakes because right now I don't have an ability to access a working environment but I think the idea is clear. So, the question is whether this is the best approach to making a query. And if there is a better, then what is it.
Essentially you can simply do exactly what was done in this post, but with two sets instead of 1 for the table valued parameter.
Using Dapper, how do I pass in the values for a sql type as param?
It uses a stored procedure and a sql table valued parameter.
If stored procedure is not an option then you can use one of following methods.
Convert your interestIds and userIds into strings
string interests = "(1, 2, 3, 4)" if lists contains numbers only or ('a1', 'b1', 'c2') if they are strings.
Then just inline them into your query
var query = #"SELECT type, id, owner_id
FROM entities
WHERE type = 'interest'
AND id IN "+ interests
+ " AND owner_id IN " + users;
This method is considered as bad practice and is an invitation to SQL injection attack (in the case of user input). Use it iff you are absolutely sure in your data.
SQL Server 2016+ has a built-in function string_split which can be used here. The function splits a string with separators into a table t(value).
Again convert lists into strings string interests="a1, a2, b3, c4"; (No single quot here)
and query
var query = #"SELECT type, id, owner_id
FROM entities
WHERE type = 'interest'
AND id IN (select value from string_split(#interests,','))
AND owner_id IN (select value from string_split(#users,','))";
For earlier versions you can create UDF with the same functionality.
create function dbo.split_string(#input varchar(max), #separator varchar(2))
returns table as
return
(with cte as(
select cast('<v>'+ REPLACE(#input, #separator, '</v><v>') +'</v>' as xml) x
)
select t.v.value('.[1]', 'varchar(max)') [value]
from cte
cross apply x.nodes('v') t(v))

Breakdown / Documentation of a SQL Query

I have a very large, complex, and undocumented database. I have a task to provide a document which would show which tables and columns have been used for all stored procedures, functions, etc.
According to my research majority of queries will have the similar format to this:
SELECT u.FirstName , u.LastName, a.AccountNumber
FROM Username u
LEFT JOIN Account a
ON a.UserID = u.UserID
~90% of tables and columns will have aliases.
Further, I do have a table with 2 columns - function/sproc name, and its SQL code.
I am looking for a method (preferably SQL, but can be C#) which would output the following results for the above SQL code:
Username - FirstName
Username - LastName
Username - UserID
Account - UserID
Account - AccountNumber
What would be the best approach to achieve this? I have tried to join each SQL code cell with INFORMATION_SCHEMA.COLUMNS but I get inaccurate results, say when column name appears in the COLUMNS table, but was not actually used for that specific table in the SQL code cell.
Thanks
Probably you want to look at the dependencies on the stored procedure/function that you are looking at?
Take a look at https://www.mssqltips.com/sqlservertip/1768/identifying-object-dependencies-in-sql-server/
e.g. if the procedure name is dbo.myproc, something like the below
SELECT '* ' + referenced_entity_name + ' - ' + referenced_minor_name
FROM sys.dm_sql_referenced_entities ('dbo.myproc', 'OBJECT')
WHERE referenced_minor_name is not null;

Search with multiple parameters in SQL Server

This question is related to both c# and SQL Server.
I want to figure out how to do a custom search.
I have three tables
Customer
CusId, Name, Telephone
Employee
EmpId, Name, Job
Appointment
AppId, Date, EmpId, CusId
My C# form has three checkboxes. I want to find the data according to those checked values.
Ex: when customer,employee,app check boxes have selected, I want to find data on depending on all those three values.
When only two or one is selected I want to search depending on those selection. Here there will be total 6 combinations.
How to write a query to get correct result when I pass those values as parameters to a stored procedure.
Do I have to write 6 stored procedures to get the result?
Are there any methods to do this easily?
Please help me to fix this matter. Thanks in advance.
With a query such as the below (would suggest in a stored proc):
-- Parameters to a SQL sproc
DECLARE #CustID INT, #EmpID INT, #AppointmentID INT
-- Set Parameters here for testing
SELECT *
FROM Appointment as A
INNER JOIN Employee as E
ON E.EmpID = A.EmpId
INNER JOIN Customer as C
ON C.CusID = A.CusID
WHERE (#CustID IS NULL OR C.CUsID = #CustID)
AND (#EmpID IS NULL OR E.EmpID = #EmpID)
AND (#AppointmentID IS NULL OR A.AppID = #AppointmentID)
You then need to pass in the parameters appropriately, either an ID if selected, or null if not filtering on one item.

Using C# to Select from SQL database Table

I have a List of UserID's and a open connection to SQL Server. How can I loop through this List and Select matching UserID with First_Name and Last_Name columns? I assume the output can be in a datatable?
many thanks
It varies slightly depending on which type of SQL you're running, but this and this should get you started.
The most expedient way of doing this would be to:
Turn the List into a string containing a comma separated list of the userid values
Supply that CSV string into an IN clause, like:
SELECT u.first_name,
u.last_name
FROM USER_TABLE u
WHERE u.userid IN ([comma separated list of userids])
Otherwise, you could insert the values into a temp table and join to the users table:
SELECT u.first_name,
u.last_name
FROM USER_TABLE u
JOIN #userlist ul ON ul.userid = u.userid
Write a function in your SQL database named ParseIntegerArray. This should convert a comma delimited string into a table of IDs, you can then join to this in your query. This also helps to avoid any SQL injection risk you could get from concatenating strings to build SQL. You can also use this function when working with LINQ to SQL or LINQ to Entities.
DECLARE #itemIds nvarchar(max)
SET itemIds = '1,2,3'
SELECT
i.*
FROM
dbo.Item AS i
INNER JOIN dbo.ParseIntegerArray(#itemIds) AS id ON i.ItemId = id.Id
This article should help you: http://msdn.microsoft.com/en-us/library/aa496058%28SQL.80%29.aspx
I've used this in the past to create a stored procedure accepting a single comma delimited varchar parameter.
My source from the C# program was a checked list box, and I built the comma delimited string using a foreach loop and a StringBuilder to do the concatenation. There might be better methods, depending on the number of items you have in your list though.
To come back to the SQL part, the fn_Split function discussed in the article, enables you to transform the comma delimited string back to a table variable that SQL Server can understand... and which you can query in your stored procedure.
Here is an example:
CREATE PROCEDURE GetSelectedItems
(
#SelectedItemsID Varchar(MAX) -- comma-separated string containing the items to select
)
AS
SELECT * FROM Items
WHERE ItemID IN (SELECT Value FROM dbo.fn_Split(#SelectedItemsIDs,','))
RETURN
GO
Note that you could also use an inner join, instead of the IN() if you prefer.
If you don't have the fn_Split UDF on your SQL Server, you can find it here: http://odetocode.com/Articles/365.aspx
I hope this helps.

Categories

Resources