SQL server table population source - sql

I have an Audit database(created by someone else).
Something is polulating it, with table sizes data (which makes sense as it is Audit database).
The SQL server has too many jobs.
I want to know what is populating the audit tables.
Is there anything like sys.comments etc? which can tell me what is populating tables or do I have to check the code inside each job?
Regards
Manjot

you could try running something like this:
SELECT DISTINCT
o.name,o.type_desc
FROM sys.sql_modules m
INNER JOIN sys.objects o ON m.object_id=o.object_id
WHERE m.definition Like '%YourTableName%'
ORDER BY 2,1
EDIT after OP mentioned SQL Server 2000
this should work on SQl Server 2000:
--remove comments to see the actual text too
SELECT DISTINCT
o.name --,c1.colid,c1.text
FROM sysobjects o
INNER JOIN syscomments c1 ON o.id = c1.id
--join to next section of code in case search value is split over two rows
LEFT OUTER JOIN syscomments c2 ON o.id = c2.id AND c2.colid=c1.colid+1
WHERE c1.text Like '%YourTableName%'
OR RIGHT(c1.text,100)+LEFT(c2.text,100) Like '%YourTableName%'
ORDER BY 1--,2

Try looking at msdb..sysjobsteps in the command column for the destination table names; this will only work if they are using T-SQL to populate the tables. If they're using an SSIS (or DTS) package, this won't work.

most likely it is being populated by triggers onteh the audited tables.

If you know what causes data to go into the audit table, you can run a (very) brief Profiler session against the database, filtering specifically on that table, while triggering the action. That will give you further steps to back-trace the root action.

Related

Last entries in any table of the database

While testing a website by adding records via the UI, I cannot always tell which tables are being updated. I would like a query - in MSSQL and a version for PostgreSQL - which returns the last entry/entries added/modified in the database, without knowing the table, so I can figure out which tables are related to the feature I am looking at.
In this case I cannot provide an example because I cannot tell which table is being updated and how.
If you are just trying to track "what table(s) is this UI writing to" without wanting to use Extended Events or Query Store to see what commands are actually running, and the service hasn't been restarted since the UI did its thing, and nobody else is using the database, you can do something like this:
SELECT TOP (10) -- or some other arbitrary number, or no TOP at all
[Schema] = s.name,
[Table] = t.name,
LastWrite = MAX(ius.last_user_update)
FROM sys.schemas AS s
INNER JOIN sys.objects AS t
ON s.[schema_id] = t.[schema_id]
INNER JOIN sys.dm_db_index_usage_stats AS ius
ON ius.[object_id] = t.[object_id]
GROUP BY s.name, t.name
ORDER BY LastWrite DESC;
But it seems like a narrow use case and can be invalidated by a lot of variables. If you want to know what your UI is doing, look at the code, or use Extended Events to monitor.

How to filter stored procedures as READ and WRITE in SQL Server

Is there any query to get all the write procedures from SQL Server?
You could try looking for every Procedure containing INSERT, DELETE or UPDATE like this:
SELECT top 10 p.name, SCHEMA_NAME(p.schema_id), *
FROM sys.sql_modules as m
INNER JOIN sys.procedures as p ON p.object_id = m.object_id
WHERE definition like '%INSERT%'
OR definition like '%UPDATE%'
OR definition like '%DELETE%'
However it will also output any procedure with a variable, a comment or anything with a name containing INSERT, DELETE or UPDATE.
You can add MERGE if your procedure may use it.

How to get column names from a query in SQL Server

Using SQL Server.
I have a very extensive query, with a lot of aliasing, etc...
Is there a way, using just SQL (stored proc is fine, but not PHP, etc), to get a list of all column names from this query? (I realize I will have to probably embed my query inside of this solution but that is fine. Just a temporary measure.)
Thanks!
If you're using SQL Server 2012 or later you can take advantage of sys.dm_exec_describe_first_result_set
SELECT name
FROM
sys.dm_exec_describe_first_result_set
('Your Query Here', NULL, 0) ;
DEMO
There are various ways that you can get the columns out of the query, such as:
select top 0 s.*
from (<your query here>) s;
Then you can parse the results.
However, I have found another approach useful. Create either a view or a table using the same logic:
select top 0 s.*
into _TempTableForColumns
from (<your query here>) s;
Then use information_schema (or the system tables if you prefer):
select *
from information_schema.columns
where table_name = '_TempTableForColumns' and schema_name = 'dbo';
drop table _TempTableForColumns;
The advantage of this approach is that you can get type information along with the column names. But the engine still has to run the query and that might take time even though no rows are returned. Although the column names and types are available after compiling, I am not aware of a way to get them without also executing the query.
After SQL Server 2008
select *
from sys.columns c
inner join sys.objects o on c.object_id = o.object_id
where o.name = 'TableName'
Before
select *
from syscolumns c
inner join sysobjects o on c.id = o.id
where o.name = 'TableName'

How to search for a specific string occurrence in stored procedures

I have a query that selects particular stored procedures, triggers and functions in my SQL database. I have retrieved 86 in total.
I need to find which of these are using a certain string inside.
This string is a name of a table.
I do not want to open each of these individually and search for it.
I'm thinking of having a script that looks inside of these and find what I need.
What I think I might need is something like from tableName or inner join on tableName or join on tableName and etc
What is a good way to do it in SQL
Thank you
To search one SQL Server database for a specific piece of text in a stored procedure you could do this:
DECLARE #SearchText VARCHAR(100) = 'TableXYZ';
SELECT DISTINCT
o.name,
o.type_desc
FROM
sys.sql_modules m
INNER JOIN sys.objects o ON m.object_id = o.object_id
WHERE
m.[definition] Like '%' + #SearchText + '%';
Obviously this is a bit of a hack and won't work out if your table name is called something daft like "SELECT" as that will just cause loads of false-positive results.
One alternative is to use the sys.dm_sql_referencing_entities system table, but my experience with this is that it can't be trusted. In general dependencies don't work very well with SQL Server due to some poor design decisions, e.g. deferred name resolution.
Microsoft SQL would cover Access, Sybase and SQL Server (and possibly more) .... But I suspect you are using SQL Server, as such I would suggest sys.dm_sql_referencing_entities rather than searching a definition for a particular string -
SELECT r.* , o.type_desc, m.definition
FROM sys.dm_sql_referencing_entities('dbo.TableName', 'OBJECT') AS r
INNER JOIN sys.all_objects AS o
ON o.[object_id] = r.referencing_id
INNER JOIN sys.sql_modules AS m
ON m.[object_id] = o.[object_id];
Here is a simple and easy to use Sql query
SELECT name
FROM sys.procedures
WHERE Object_definition(object_id) LIKE '%strHell%'
And here's a link for more info

ambiguous column name, my WHERE statement is already taken up for other purposes

So i have this problem where i need an INNER JOIN to connect my imagetable to my product table, and i've already tried to specify each coloumn name with a connection to the tables as you can see below. When it comes to my WHERE statement, thats where it gets tricky. Since i need to save my ProductID as a variable called pid for other codebehind purposes.
SELECT * FROM ProductTBL p
INNER JOIN ImageTBL img on p.ProductID = img.ProductID
WHERE (ProductID = #pid)
When i run this code it will tell me ProductID is an ambiguous column name and when i try
to specify my Where statement even further like this:
WHERE (p.ProductID = #pid)
It will give me another error telling me that no data is bound to my certain rows from which i'm taken out data from. This error is only there when i don't specify the Where statement like the one above.
Any input at all will be greatly appreciated :)
PS: im running MSSQL if that has anything to say.
I know two ways of doing this. The 2nd way is probably the recommended way (it should run quicker).
Way 1)
Run it in a two step statement. I don't think you can use the * in the inner SELECT statement:
SELECT * FROM (
SELECT p.ProductID, [other needed fields]
FROM ProductTBL p
INNER JOIN ImageTBL img on p.ProductID = img.ProductID
) as x
WHERE (ProductID = #pid)
The inner SELECT p.ProductID says to explicitly return the ProductID from the ProductTBL. That ProductID field can then be used in your WHERE statement because it's in the outer SQL statement.
Way 2)
Put the "WHERE" criteria as part of the join
SELECT *
FROM ProductTBL p
INNER JOIN ImageTBL img on p.ProductID = img.ProductID AND p.ProductID = #pid
The "ambiguous column name" message is a SQL Server error, and you fixed it by specifying "WHERE p.ProductID = #pid". Yes, you need the p. in front of ProductID, because ImageTBL also has a column with the same name.
The "no data is bound" error is not coming from SQL. You now have a correct SQL statement, but it is apparently returning no records, at least for the value of #pid that you are running it with.
You are calling this from an application that is trying to do something with the data, right? That is where the "no data is bound" error is coming from.
You can separate the two parts of your problem by running your SQL statements in a SQL Server Management Studio query window, and plugging in your desired value for #pid. Then you can run your application in debug mode, and check whether it is receiving the same data you see in Management Studio. Here's one guess: your application is not passing #pid correctly, and the SQL statement is returning records where p.ProductID = ''. See if that's what's going on.
It can be an issue with your code. Try to run the query with hard core value of product ID and run it in the database console.
It doesn't appear to be a database issue
Ok, well its the where statment that has the problem. You need to prefix your productID with your table alias. Table alias' are good, I've no doubt you have realised that when you type SELECT * From MyTable T, and then go back to choose your columns, you get an intellisnce list of columns when you replace * by T. Aliasing tables is always good. Say you have two tables T1 and T2 and Columns C1, C2, C3 in T1 and C4, C5, C6 in T2. You script your stored procedure and it works. Sometime later somone comes along and adds c column named C2 to T2, then your procedure will probably break if you have not prfixed the table name on the columns. So even if there is no current ambiguity and you never change your stored proc, using prefixed is always more robust.
Its always a good idea to explicitly state you columns rather than using *, because once again adding columns can break your proc and also if you have a column name incorrect, SSMS will underline it with a little red squigle.