How to parse data in SQL Server 2008? - sql-server

I have a column name called Username in my table in SQL Server 2008.
Username has following data
Username
corp\abc
corp\petern
corp\timw
and so on
I need my Username to be
Username
abc
petern
timw
how do I parse the data in Username to skip corp\ ?
Thanks.

You could use PARSENAME to split the data but the function uses dot (.) as the delimiter. So, you have to first replace the backward slashes (\) with period or dot (.).
Click here to view the demo in SQL Fiddle.
Script:
CREATE TABLE users
(
username VARCHAR(30) NOT NULL
);
INSERT INTO users (username) VALUES
('corp\abc'),
('corp\corporate\'),
('corp\yescorp'),
('corp\def'),
('\corpabc\'),
('corpabc\');
SELECT username
, PARSENAME(REPLACE(username, '\', '.'), 1) AS usernameonly
FROM users;
Output:
USERNAME USERNAMEONLY
----------------- ------------
corp\abc abc
corp\corporate\
corp\yescorp yescorp
corp\def def
\corpabc\
corpabc\

You might use following expression to extract username:
select substring (username, charindex ('\', username, 1) + 1, len(username))
If there is no backslash in username function will return entire username - practical if you mix sql server and Windows authentication.

Update dbo.Users
Set Username = replace(Username, 'corp\\', '');
Please check the quoting beforehand, by first checking whether the results of select seem ok (in general it's a good practice with data updating statements):
select replace(Username, 'corp\\', '') from dbo.Users

You can get the username like this:
SELECT RIGHT('corp\username',LEN('corp\username')-PATINDEX('%\%','corp\username'))
=>
SELECT RIGHT(username,LEN(username)-PATINDEX('%\%',username))
This work on text, nvarchar(n - max)

Related

How to update the SQL Server table based on different column value

I would like to update table called people from:
to
Could you please help?
You need to parse out the beginning of the email address to add it to the domain name. Do that by finding the CHARINDEX of the # symbol, then subtracting one. Use that value as the length parameter in a LEFT function call.
Once you have the name from the email address, CONCATenate it to the static value of your domainname\.
I included a WHERE clause that you may want to use if you have a large number of rows where the Username is already correct and you don't want to waste a bunch of writes replacing a string with a duplicate of that same string. You could leave the WHERE off if you prefer.
UPDATE People
SET Username = CONCAT('domainname\',LEFT([E-mailAddress],CHARINDEX('#',[E-mailAddress])-1))
WHERE
Username <> CONCAT('domainname\',LEFT([E-mailAddress],CHARINDEX('#',[E-mailAddress])-1));
If you are working on earlier versions (cause CONCAT() is for 2012+ versions) and also if you have NULLs in the UserName column, you can do like
CREATE TABLE T(
[E-MailAddress] VARCHAR(50),
UserName VARCHAR(45)
);
INSERT INTO T VALUES
('abc#domainname.com', 'abc'),
('zxc#fhlbdm.com', NULL),
('MNO#domainname.com', 'MNO'),
('pqr#domainname.com', 'pq'),
('tyu#domainname.com', 'domainname\tyu');
UPDATE T
SET UserName = 'domainname\' + LEFT([E-MailAddress], CHARINDEX('#', [E-MailAddress])-1)
WHERE 'domainname\' + LEFT([E-MailAddress] , CHARINDEX('#', [E-MailAddress])-1) <> UserName
OR
UserName IS NULL;
SELECT *
FROM T;

Oracle ROWTOCOL Function oddities

I have a requirement to pull data in a specific format and I'm struggling slightly with the ROWTOCOL function and was hoping a fresh pair of eyes might be able to help.
I'm using 10g Oracle DB (10.2) so LISTAGG which appears to do what I need to achieve is not an option.
I need to aggregate a number of usernames into a string delimited with a '$' but I also need to concatenate another column to to build up email addresses.
select
rowtocol('select username_id from username where user_id = '||s.user_id|| 'order by USERNAME_ID asc','#'||d.domain_name||'$')
from username s, domain d
where s.user_id = d.user_id
(I've simplified the query specific to just this function as the actual query is quite large and all works except for this particular function.)
in the DOMAIN Table I have a number of domains such as 'hotmail.com','gmail.com' etc
I need to concatenate the username, an '#' symbol followed by the domain and all delimited with a '$'
such as ......
joe.bloggs#gmail.com$joeblogs#gmail.com$joe_bloggs#gmail.com
I've battled with this and I've got close but in reverse?!.....
gmail.com$joe.bloggs#gmail.com$joeblogs#gmail.com$joe_bloggs
I've also noticed that if I play around with the delimiter (,'#'||d.domain_name||'$') it has a tendency to drop off the first character as can be seen above the preceding '#' has been dropped from the first email address.
Can anyone offer any suggestions as to how to get this working?
Many Thanks in advance!
Assuming you're using the rowtocol function from OTN, and have tables something like:
create table username (user_id number, username_id varchar2(20));
create table domain (user_id number, domain_name varchar2(20));
insert into username values (1, 'joe.bloggs');
insert into username values (1, 'joebloggs');
insert into username values (1, 'joe_bloggs');
insert into domain values (1, 'gmail.com');
Then your original query gets three rows back:
gmail.com$joe.bloggs
gmail.com$joe_bloggs#gmail.com$joebloggs
gmail.com$joe_bloggs#gmail.com$joebloggs
You're passing the data from each of your user IDs to a separate call to rowtocol, which isn't really what you want. You can get the result I think you're after by reversing it; pass the main query that joins the two tables as the select argument to the function, and have that passed query do the username/domain concatenation - that is a separate step to the string aggregation:
select
rowtocol('select s.username_id || ''#'' || d.domain_name from username s join domain d on d.user_id = s.user_id', '$')
from dual;
which gets a single result:
joe.bloggs#gmail.com$joe_bloggs#gmail.com$joebloggs#gmail.com
Whether that fits into your larger query, which you haven't shown, is a separate question. You might need to correlate it with the rest of your query.
There are other ways to string aggregation in Oracle, but this function is one way, and you already have it installed. I'd look at alternatives though, such as ThomasG's answer, which make it a bit clearer what's going on I think.
As Alex told you in comments, this ROWTOCOL isn't a standard function so if you don't show its code, there's nothing we can do to fix it.
However you can accomplish what you want in Oracle 10 using the XMLAGG built-in function.
try this :
SELECT
rtrim (xmlagg (xmlelement (e, s.user_id || '#' || d.domain_name || '$')).extract ('//text()'), '$') whatever
FROM username s
INNER JOIN domain d ON s.user_id = d.user_id

Retrieving Oracle Password_Verify_Function

I am an IS auditor and I would like to check how we can retrieve the PASSWORD_VERIFY_FUNCTION assigned to users. I understand the script utlpwdmg.sql can be executed to setup the default password resource limits.
If changes were made using ALTER PROFILE, the script utlpwdmg.sql will not show the latest settings.
Please let me know what SQL commands I can execute to show what is the PASSWORD_VERIFY_FUNCTION stored and used in the system.
You can use this query to see source code of stored proc:
--Source of all password functions.
select *
from dba_source
where owner = 'SYS'
and name in
(
--The name of all password functions in use.
--See DBA_USERS.PROFILE to determine which user is using which profile.
select limit
from dba_profiles
where resource_name = 'PASSWORD_VERIFY_FUNCTION'
--Yes, this is intentionally the string 'NULL', that's what Oracle uses here.
and limit <> 'NULL'
)
order by name, line;
To find out what users are using PASSWORD_VERIFY_FUNCTION, you need to find out which profiles are using the function and then see which users are assigned that profile.
select profile from dba_profiles where limit = 'PASSWORD_VERIFY_FUNCTION';
select username from dba_users where profile = ;

Alternatives for parsing sql query

I have an audit running on multiple tables in my database that is triggered when a user runs a select against said tables. I am attempting to parse the 'statement' returned from the audit and get a username out of the information. Here is my query:
SELECT *
FROM (SELECT LastName,
queryLastName,
statement,
Event_time AS CurrentDateTime,
'AuditFile' AS SourceTable
FROM (SELECT statement,
event_time,
SUBSTRING(server_principal_name, 9, len(server_principal_name) - 8) AS LastName,
SUBSTRING(SUBSTRING(statement, CHARINDEX('LastName like ''%', statement) + 16, 20), 0, CHARINDEX('%''', SUBSTRING(statement, CHARINDEX('LastName like ''', statement) + 16, 20))) AS queryLastName
FROM #MyTempTable
WHERE server_principal_name != 'abc'
AND CHARINDEX('LastName like ''%', statement) > 0) AS A) AS B
WHERE querylastname != ''
Now, the above query will correctly return any SELECT query that has Lastname like '%name%', but i'd also like to be able to return names looked up in other ways such as '%name' or '_name__'. Are there any more elegant solutions to solve this problem?
Edit: The Audit file contains a column called 'Statement'. This holds what the query was that triggered the audit. For example,
SELECT * from tblUserNames where LastName Like '%Smith%'
will trigger the audit and place the above query in statement.
My query takes Smith out of the string however if a user entered '%Smith' instead, the query would not work as it does not pick up variations. Same goes for 'Smith', 'Smith' etc. If possible, I need a more elegant way to handle multiple situations where a user could look up a name using wildcards on either end of the name.

Find if correct password with hash and random salt

I have a database with users and I want to have a random salt for each user that is saved in the column Salt and a hash of their salt+password in the field password.
I can insert them like this:
INSERT INTO users([Username], [Password], [Salt])
VALUES('David', HASHBYTES('SHA1', 'randomgeneratedsalt' + 'theirpw'), 'randomgeneratedsalt')
But how do I select them?
My own try is:
select *
from users
where Username = 'David'
AND Password = HASHBYTES('SHA1', Salt + 'enteredpw')
Of course I can select the salt for the user that is trying to login, but I'd like to do it without doing so.
You select them by username, which must be unique. After you locate the user you can compare the presented password hash against the stored one. Only need be careful to display the same error whether username was not found or hash don't match (ie. prevent information disclosure that the username is valid).

Resources