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;
Related
I wanted to know that what may be the best practice to search for keywords or sentence in SQL Server.
Suppose I have a table say products with name, description and keywords. I have a search function in my website where the user may type in anything (sentence or single word).
I query the product table columns using like clause and shortlist the list to rows containing the search criteria.
To reduce the response time in case if the volume of data in product table is large, I add a pagination query of 10.
My current query
select *
from
(select
srno as productid, name +' '+ descriptions +' '+ keywords as search
from
ProductDetails) PD
where
PD.search LIKE '%bed%'
OR PD.search LIKE '%sheets%'
Here I have combined the three columns namely name,descriptions and keywords and I am searching for "bed sheets" in my product table
Is the above explained scenario a good practice?
Table Structure
ProductDetails example
srno|Name|Description|keywords
1|Floral Bed Sheets|..some text..|bed sheets
2|Square Pillow Covers|.. some text..|pillow covers square
Is it proper to place keywords in a separate column or should I create a new table for keywords.
If I have to create a new table for keywords, how to modify the above query?
Thanks in advance
I have 3 tables (for example 3, but in real over than 30 tables with this conditions) in my SQL Server database: post, user, person.
post: (post_id, post_text, user_id)
user: (user_id, user_name, person_id)
person: (person_id, person_phone, person_email)
Now, in C#, I want an algorithm that creates a query that get result like this:
post.post_id, post.post_text, post.user_id, user.user_id, user.user_name, user.person_id, person.person_id, person.person_email
and I use this method for fill a SqlDataReader in C# for reading and accessing all column values from these records.
I know that the common way to get that result directly and manually using of 'Join' statement, but it is waste time if tables count is very much. So, I want an algorithm that generates this query for manipulate in C# programming.
Thanks a lot.
To query all column names from your tables, you can use:
SELECT obj.Name + '.' + col.Name AS name
FROM sys.columns col
INNER JOIN sys.objects obj
ON obj.object_id = col.object_id
WHERE obj.Name IN ('post', 'user', 'person')
ORDER BY name
Then, for how to call this from C# using SqlDataReader, you can use this documentation: https://msdn.microsoft.com/en-us/library/haa3afyz(v=vs.110).aspx
select post1.post_id, post1.post_text, post1.user_id, user1.user_id, user1.user_name, user1.person_id, person1.person_id, person1.person_email from post post1 inner join user user1 on user1.user_id=post1.user_id inner join person person1 on person1.person_id=user1.person_id
I have a sql (transact sql - SQL server 2012) which used to fetch names of customers from a table (Customer) who has valid addresses (from table Details):
Select Customer.Name, Details.Address
from Customer
left outer join Details on Details.Customer = Customer.Name
This used to send back each record (name) row for each customer every time from the db server. No multiple records are fetched.
Recently I needed to modify this sql text in order to fetch even the name of the books they have borrowed as per the database, which is saved in another table (Lending). Now the script looks like:
Select Customer.Name, Details.Address, Lending.BookName
from Customer
left outer join Details on Details.Customer = Customer.Name
left outer join Lending on Lending.CustomerName = Customer.Name
It is returning the records properly, but now I have got a problem. Since a customer can borrow multiple books, the returned data has multiple rows for the same customer showing multiple book names. According to my software specification I need to fetch one line for each customer and in that one row i need to append all the book names in a single column.
Can someone help me with this: How to append multiple data for same record in a single column such as:
Name Address BookName
Somdip XX Brief History of Time,Headfirst SQL,Headfirst C#
instead of
Name Address BookName
Somdip XX Brief History of Time
Somdip XX Headfirst SQL
Somdip XX Headfirst C#
??
I used the above sql text with 'where' and 'order by' clauses such as :
SELECT Name,
Address ,
Split.a.value('.', 'VARCHAR(100)') BookName
FROM (SELECT Name,
Address ,
Cast ('<M>' + Replace(BookName, ',', '</M><M>') + '</M>' AS XML) AS Data
FROM [table] where ID = '1' order by Name) AS A
CROSS APPLY Data.nodes ('/M') AS Split(a)
and it is giving me an error: The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP, OFFSET or FOR XML is also specified.
try this:
SELECT Name,
Address ,
Split.a.value('.', 'VARCHAR(100)') BookName
FROM (SELECT Name,
Address ,
Cast ('<M>' + Replace(BookName, ',', '</M><M>') + '</M>' AS XML) AS Data
FROM [table]) AS A
CROSS APPLY Data.nodes ('/M') AS Split(a)
While I think this is generally a bad idea - returning multiple data items in a single cell - there are a number of ways to go about it, with different performance concerns.
What you're looking for is here: Concatenate many rows into a single text string?
I am using below table structure, I want to create a view which will show a FirstName of ReportsTo field shown below.
Please let me give a suggestion how to create that view which will display all the reports to 's first name with (',') comma separator.
You join a table to itself just like any other join. The main this is to make sure both tables are aliased with differnt aliases
Your problem is that you have a one to many relationship stored in the table which is a huge design mistake. For the future, remember that anytime you think about storing information a comma delimted list, then you are doing it wrong and need a related table instead. So first you have to split the data out into the related table you should have had instead with two columns, EmplCode and ReportsTo (with only one value in reports to), then you can do the join just like any other join. We use a function that you can get by searching around the internet called fn_split to split out such tables when we get this type of infomation in client files.
If you search out fn_split, then this is how you can apply it:
Create table #UnsplitData (EmpCode varchar (10), ReportsTo varchar(20), FirstName varchar (10))
insert into #UnsplitData
values ('emp_0101', 'emp_0102,emp_0103', 'John')
, ('emp_0102', 'emp_0103', 'Sally')
, ('emp_0103', Null, 'Steve')
select *, employee.FirstName + ', ' + Reports.FirstName
from #UnsplitData Employee
join
(
select t.EmpCode , split.value as Reportsto, ReportName.Firstname
from #UnsplitData t
cross apply dbo.fn_Split( ReportsTo, ',') split
join #UnsplitData ReportName
on ReportName.EmpCode = split.value
) Reports
On Employee.EmpCode = Reports.empcode
From what I gather, I think you're trying to get the Firstname column and the ReportsTo column separated by a comma:
SELECT FirstName + ', ' + ReportsTo
FROM table
Edit: judging from the comments he's trying to do something else? Can someone rephrase for me?
SELECT E.*,
R.FirstName
FROM Employees E
JOIN Employees R
ON E.ReportsTo LIKE '%' + R.EmpCode + '%'
I'm trying to manually map some rows to instances of their appropriate classes. I know that I need to use every column of every table, and map all of those columns from one table into a given class.
However, I was wondering if there would be an easier way to do it. Right now, I have a class called School and a class called User. Each of these classes has a Name property, and other properties (but the ´Name` one is the important one, since it is a mutual name for both classes).
Right now, I am doing the following to map them down.
SELECT u.SomeOtherColumn, u.Name AS userName, s.SomeOtherColumn, s.Name AS schoolName FROM User AS u INNER JOIN School AS s ON something
I would love to do the following, but I can't, since Name is a mutual name between the classes.
SELECT u.*, s.* FROM User AS u INNER JOIN School AS s ON something
This however generates an error since they both have the column Name. Can I prefix them somehow? Like this for instance?
u.user_*, s.school_*
So that every column of each of those tables have a prefix? For instance user_Name and school_Name?
Years ago I wrote a bunch of functions and procedures to help me with developing automatic code-generation routines for SQL Servers and applications using dynamic SQL. Here is the one that I think would be most helpful to your situation:
Create FUNCTION [dbo].[ColumnString2]
(
#TableName As SYSNAME, --table or view whose column names you want
#Template As NVarchar(MAX), --replaces '{c}' with the name for every column,
#Between As NVarchar(MAX) --puts this string between every column string
)
RETURNS NVarchar(MAX) AS
BEGIN
DECLARE #str As NVarchar(MAX);
SELECT TOP 999
#str = COALESCE(
#str + #Between + REPLACE(#Template,N'{c}',COLUMN_NAME),
REPLACE(#Template,N'{c}',COLUMN_NAME)
)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA= COALESCE(PARSENAME(#TableName, 2), N'dbo')
And TABLE_NAME = PARSENAME(#TableName, 1)
ORDER BY ORDINAL_POSITION
RETURN #str;
END
This allows you to format all of the column names of a table or view any way that you want. Simply pass it a table name, and a Template string with '{c}' everywhere that you want the column name inserted for each column. It will do this for every column in #TableName, and add the #Between string in between them.
Here is an example of how to vertically format all of the column names for a table, renaming them with a prefix in a way that is suitable for inclusion into a SELECT query:
SELECT dbo.[ColumnString2](N'yourTable', N'
{c} As prefix_{c}', N',')
This function was intended for use with dynamic SQL, but you can use it too by executing it in Management Studio with your output set to Text (instead of Grid). Then cut and paste the output into your desired query, view or code text. (Be sure to change your SSMS Query options for Text Results to raise the "maximum number of characters displayed" from 256 to the max (8000). If that still gets cut off for you, then you can change this procedure to a function that outputs each column as a separate row, instead of as one single large string.)