I have a scenario, where I need to compare data between two servers.
Long story short, I need a result set which gives the output like
SchemaName|TableName|RowCount_PrimaryKey
Whenever a new student joins a unique schema is created say Stu1200 and this schema has 5 tables like
stu1200.class
stu1200.sub
stu1200.avg
stu1200.work
stu1200.blabla
There are 500 students in our database. So 500 schema. I need to compare all the tables of work of 500 students.
In order to do so I need to get the counts of the primary key, say StuID. So I need to get all the 500 schemas with the table like work.
Something like
SchemaName TableName StuID_Count
stu1200 Work 70
Stu1201 Work 112
Stu1202 Work 9
How can this be done? I have a script which does row counts of the table but its of useless, I need the row counts based only on the primary key.
Note: using SQL Server 2000 :(
Thanks in advance for sharing your suggestions/experience.
Your design is highly questionable but here is a way to get a relatively up-to-date count in an efficient manner. In SQL Server 2005+:
DECLARE #tablename SYSNAME;
SET #tablename = N'Work';
SELECT
SchemaName = OBJECT_SCHEMA_NAME([object_id]),
TableName = #tablename,
RowCount_PrimaryKey = SUM([rows])
FROM sys.partitions
WHERE OBJECT_NAME([object_id]) = #tablename
AND index_id IN (0,1)
GROUP BY OBJECT_SCHEMA_NAME([object_id])
ORDER BY SchemaName;
Just noticed SQL Server 2000.
DECLARE #tablename SYSNAME;
SET #tablename = N'Work';
SELECT
SchemaName = u.name,
TableName = #tablename,
i.rows
FROM
sys.sysindexes AS i
INNER JOIN sys.sysobjects AS o
ON i.id = o.id
INNER JOIN sys.sysusers AS u
ON o.uid = u.uid
WHERE i.indid IN (0,1)
AND o.name = #tablename;
Related
I made a lot of views with 7-20 columns in each of them. I need to make a query which will return me the list of tables and columns on which is related every column in every view.
Example of my view:
CREATE VIEW example AS
SELECT t.NAME, t.AGE, t.ADDRESS, p.MOBILE, p.LAPTOP ...
FROM person t, device p
WHERE ...
Query result (needed):
TABLE COLUMN
person NAME
person AGE
person ADDRESS
device MOBILE
device LAPTOP
Is this possible, and how? It saves me a lot of time (there is over 900 columns in all views).
Thanks
Yet you can have this query to pull all the views present in your database along with columns present in them views.
SELECT v.name AS View_Name
,c.name AS Column_Name
FROM sys.views v
INNER JOIN sys.all_columns c ON v.object_id = c.object_id
Here is a more elaborated solution, the idea is to convert views to temp tables with no records (select top 0 * from ...) and for each table retrieve the column names from INFORMATION SCHEMA:
---Create this table First
CREATE TABLE dbo.Views_Columns(
id INT IDENTITY(1,1) PRIMARY KEY,
ViewName varchar(100),
ColumnName varchar(100)
)
--START
DECLARE #CurrentView varchar(100)
DECLARE #CurrentSchema varchar(50)
--Temp table #AllViews stores all views names
SELECT s.name as SchemaName, v.name as ViewName, 0 as Processed
INTO #AllViews
FROM sys.views v INNER JOIN SYS.schemas s ON v.schema_id = s.schema_id
WHILE EXISTS (select * from #AllViews WHERE Processed = 0)
BEGIN
--Clean up our temp table
IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'temp')
BEGIN
DROP TABLE dbo.temp
END
SELECT TOP 1 #CurrentView = ViewName, #CurrentSchema = SchemaName
FROM #AllViews WHERE Processed = 0
EXEC('SELECT TOP 0 * INTO dbo.temp FROM '+#CurrentSchema+'.'+#CurrentView)
INSERT INTO Views_Columns
SELECT #CurrentSchema+'.'+#CurrentView, Column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'temp'
UPDATE #AllViews SET Processed = 1 where ViewName = #CurrentView
END
SELECT * FROM Views_Columns
--END
Please help me with a simple procedure, lets say on Sql Server (2005, 2008, does not matter).
I have table dbo.[columns] with 1000 lines, which all are the names for some specific table names from a database.
Bottom line is that I need to create a procedure which will parse all 1000 lines of tables,
for each table name found in dbo.[columns] to execute the following
select: select count(*), ''''+[column_name]+'''' from dbo.[column_name]
The result should be like this:
count(*) table_name:
100 employees
0 ex_employees
25 addresses
10 birthdays
Any hints?
Thanks in advance,
Bogdan
SELECT COUNT(Column_With_List_Of_Table_Names_Here)
, Column_With_List_Of_Table_Names_Here
FROM YourDatabase.dbo.YourTable
GROUP BY Column_With_List_Of_Table_Names_Here;
Maybe not what are you asking, but should get the results I think you want. You can use system views to get the row count for each table without running COUNT(*)
SELECT i.rowcnt, o.name FROM sysindexes i
LEFT JOIN sys.objects o ON i.id = o.object_id
WHERE indid <2
ORDER BY name
or
SELECT SUM (row_count) AS ROWS, o.Name AS TableName
FROM sys.dm_db_partition_stats s
LEFT JOIN sys.objects o ON s.object_id = o.object_id AND (index_id=0 or index_id=1)
GROUP BY o.Name
*2nd query should be more precise
Inner joining this queries to your dbo.[columns] can filter the results only for your desired tables.
Try this using CURSOR And Dynamic sql
CREATE TABLE #temp(count_ int,table_name varchar(50))
DECLARE #column_Name VARCHAR(50)
DECLARE #query VARCHAR(500)
DECLARE table_cursor CURSOR FOR
SELECT [column_name] from dbo.[column_name]
OPEN product_cursor
FETCH NEXT FROM product_cursor INTO #column_Name
WHILE ##FETCH_STATUS = 0
BEGIN
SET #query='INSERT INTO #temp SELECT'+ #column_Name+',COUNT(*) FROM'+ #column_Name
EXEC sp_executesql #SQLStatement=#query
/*this will insert the coresponding table name and its row count to #temp*/
END
CLOSE product_cursor
DEALLOCATE product_cursor
select * from #temp
I want to find out whether the table has an identity column or not. Table is unknown to me. I have not done the structure of the table. Using Query?
I am using Sql Server Compact Edition.
IF (OBJECTPROPERTY(OBJECT_ID('TABLE_NAME'), 'TableHasIdentity') = 1)
ObjectProperty is available starting sql server 2008 Reference:
OBJECTPROPERTY
This query returns a table's identity column name:
CREATE PROCEDURE dbo.usp_GetIdentity
#schemaname nvarchar(128) = 'dbo'
,#tablename nvarchar(128)
AS
BEGIN
SELECT OBJECT_NAME(OBJECT_ID) AS TABLENAME,
NAME AS COLUMNNAME,
SEED_VALUE,
INCREMENT_VALUE,
LAST_VALUE,
IS_NOT_FOR_REPLICATION
FROM SYS.IDENTITY_COLUMNS
WHERE OBJECT_NAME(OBJECT_ID) = #tablename
AND OBJECT_SCHEMA_NAME(object_id) = #schemaname
END
Then form the code side.
Call this stored procedure using the datareader role, then check datareader.hasrows(). If the condition value is true (1), then the table has identity column if set. If not then it doesn't have an identity column.
I know it's long time ago but i found this helpful
try this :
IF EXISTS (SELECT * from syscolumns where id = Object_ID(#TABLE_NAME) and colstat & 1 = 1)
BEGIN
-- Do your things
END
Any of the below queries can be used to check if an Identity Column is present in the table
1)
SELECT *
FROM sys.identity_columns
WHERE OBJECT_NAME(object_id) = 'TableName'
2)
SELECT *
FROM sys.identity_columns
WHERE object_id = (
SELECT id
FROM sysobjects
WHERE name = 'TableName'
)
I would just like to add this option as well as I think it is the simplest
SELECT COLUMNPROPERTY(OBJECT_ID('TableName'),'ColumnName','isidentity')
One way to do this would be to make use of the stored procedure sp_help. I.e:
sp_help MyTable
This will return a DataSet that has all the information you would need on the table. There is a specific Table that has information on identities.
I.e:
If it does not contain an identity field, the Identity column will say: "No identity column defined".
#Pranay: he said Compact Edition. Stored procedures aren't supported, and there is no sys.anything.
This is the call:
SELECT Count(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE AUTOINC_INCREMENT IS NOT NULL AND TABLE_NAME='this_table'
It will return either 1 (true) or 0 (false).
...
declare #tblhasIdentCol bit = IF (IDENT_CURRENT( #dbName +'.'+ #schemaName +'.'+ #tableName ) IS NOT NULL , 1 , 0 )
You get numeric value if table has identity
Very simple answer would be to run this:
SELECT IDENT_CURRENT('TABLE-NAME')
This would give max value of identity column if exists, if the column doesn't exist, it gives 1 as result.
Based on max value, you can identify which column is having that and determine the identity column.
This the query that get u all the tableNames, columnnames of the table, and is_identity or not in the selected database
SELECT
sys.columns.name
, sys.tables.name
, is_identity
FROM sys.columns
INNER JOIN sys.tables ON sys.tables.object_id = sys.columns.object_id
AND sys.columns.is_identity = 1
CREATE FUNCTION dbo.fnTableHasIdentity(#Tbl sysname)
RETURNS TINYINT
BEGIN
RETURN OBJECTPROPERTY(OBJECT_ID(#Tbl), 'TableHasIdentity')
END
--As simple as that!
select t.name as TableName,c.name as ColumnName
from sys.identity_columns c
inner join sys.tables t on c.object_id = t.object_id
where t.name = 'TableName'
If you like me, needed to be able to do this for tables in an arbitrary database, then I found the following solution:
IF EXISTS (
SELECT 1
FROM [database name].sys.identity_columns AS id_col
INNER JOIN [database name].sys.objects
ON objects.object_id = id_col.object_id
INNER JOIN [database name].sys.schemas
ON schemas.schema_id = objects.schema_id
AND schemas.name = 'schema name'
WHERE OBJECT_NAME(id_col.object_id, DB_ID('database name')) = 'table name'
) SELECT 1 ELSE SELECT 0
you can get the 1 or 0 Boolean Form if the current table has identity Columns by using this
SELECT Count(Column_ID) FROM sys.identity_columns WHERE OBJECT_NAME(object_id) = 'tableName'
One way to list all Tables with their identity column if it exists
to get you desired table add at the end of the filter "and o.name='TableName'"
where Tbale Nam is the table you are looking for
SELECT o.[Name][TableName],i.[name][IdentityColName] FROM
sys.objects o
left outer join sys.identity_columns i on i.object_id=o.object_id
where o.type='U'
This is the query I'm using:
DELETE TB1.*, TB2.*
FROM TB1
INNER JOIN TB2 ON TB1.PersonID = TB2.PersonID
WHERE (TB1.PersonID)='2'
It's working fine in MS Access but getting error (Incorrect syntax near ','.) in SQL Server Express 2005.
How to solve it? Please help.
You cannot DELETE from multiple tables with a single expression in SQL 2005 - or any other standard SQL for that matter. Access is the exception here.
The best method to get this effect is to specify FOREIGN KEYS between the table with an ON DELETE trigger.
Why you don't use a DELETE CASCADE FK ?
This cannot be done in one statement. You will have to use 2 statements
DELETE FROM TB1 WHERE PersonID = '2';
DELETE FROM TB2 WHERE PersonID = '2';
As i know, you can't do it in a sentence.
But you can build an stored procedure that do the deletes you want in whatever table in a transaction, what is almost the same.
I don't think you can delete from multiple tables at once (though I'm not certain).
It sounds to me, however, that you would be best to achieve this effect with a relationship that cascades deletes. If you did this you would be able to delete the record from one table and the records in the other would be automatically deleted.
As an example, say the two tables represent a customer, and the customer's orders. If you setup the relationship to cascade deletes, you could simply delete record in the customer table, and the orders would get deleted automatically.
See the MSDN doc on cascading referential integrity constraints.
Specify foreign key for the details tables which references to the primary key of master and set Delete rule = Cascade .
Now when u delete a record from the master table all other details table record based on the deleting rows primary key value, will be deleted automatically.
So in that case a single delete query of master table can delete master tables data as well as child tables data.
Use this in procedure
declare cu cursor for SELECT [name] FROM sys.Tables where [name] like 'tbl_%'
declare #table varchar(100)
declare #sql nvarchar(1000)
OPEN cu
FETCH NEXT FROM cu INTO #table
WHILE ##FETCH_STATUS = 0
BEGIN
set #sql = N'delete from ' + #table
EXEC sp_executesql #sql
FETCH NEXT FROM cu INTO #table
END
CLOSE cu;
DEALLOCATE cu;
I use this for cleaning up data in test/development databases. You can filter by table name and record count.
DECLARE #sqlCommand VARCHAR(3000);
DECLARE #tableList TABLE(Value NVARCHAR(128));
DECLARE #TableName VARCHAR(128);
DECLARE #RecordCount INT;
-- get a cursor with a list of table names and their record counts
DECLARE MyCursor CURSOR FAST_FORWARD
FOR SELECT t.name TableName,
i.rows Records
FROM sysobjects t,
sysindexes i
WHERE
t.xtype = 'U' -- only User tables
AND i.id = t.id
AND i.indid IN(0, 1) -- 0=Heap, 1=Clustered Index
AND i.rows < 10 -- Filter by number of records in the table
AND t.name LIKE 'Test_%'; -- Filter tables by name. You could also provide a list:
-- AND t.name IN ('MyTable1', 'MyTable2', 'MyTable3');
-- or a list of tables to exclude:
-- AND t.name NOT IN ('MySpecialTable', ... );
OPEN MyCursor;
FETCH NEXT FROM MyCursor INTO #TableName, #RecordCount;
-- for each table name in the cursor, delete all records from that table:
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sqlCommand = 'DELETE FROM ' + #TableName;
EXEC (#sqlCommand);
FETCH NEXT FROM MyCursor INTO #TableName, #RecordCount;
END;
CLOSE MyCursor;
DEALLOCATE MyCursor;
Reference info:
sysobjects
sysindexes
SQL Server Cursors
Generally I do deletions from multiple tables with one query.
It works correct with PostgreSQL, but doesn't work for MSSQL, and that's why I got here.
With Postgres (I don't know about other DBs) you can do:
WITH obsolete_ids AS (
SELECT pr_r."ID" AS ids
FROM "PULL_REQUEST" pr_r
WHERE 1=1
AND pr_r."STATUS" IN (1)
) , del_commit_junc AS (
DELETE
FROM "PR_TO_COMMIT"
WHERE "REQUEST_ID" IN (SELECT ids FROM obsolete_ids)
)
DELETE
FROM "PULL_REQUEST" pr_out
WHERE pr_out ."ID" IN (SELECT ids FROM obsolete_ids)
Actually In my original Query I delete foreign keys from 2 more tables, but here I just paste an example.
That way I solved problem with Foreign Keys in "PR_TO_COMMIT" table.
The way I am using to Delete rows from multiple tables in SQL Server?
The most important is to use on delete cascade when creating a foreign key in the table
#Table 1 Create:#
create table Customer_tbl
(
C_id int primary key,
C_Name varchar(50),
C_Address varchar(max),
City varchar(50)
);
#Table 2: Create with Foreign Key Constraints#
create table [order]
(
Ord_Id int primary key,
Item varchar(50),
Quantity int,
Price_Of_1 int,
C_id int foreign key references Customer_tbl(C_id)
on delete cascade
);
delete from Customer_tbl where C_id = 2;
You can use something like the following:
DECLARE db_cursor CURSOR FOR
SELECT name
FROM master.dbo.sysdatabases
WHERE name IN ("TB2","TB1") -- use these databases
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO #name
WHILE ##FETCH_STATUS = 0
BEGIN
DELETE FROM #name WHERE PersonID ='2'
FETCH NEXT FROM db_cursor INTO #name
END
CREATE PROCEDURE sp_deleteUserDetails
#Email varchar(255)
AS
declare #tempRegId as int
Delete UserRegistration where Email=#Email
set #tempRegId = (select Id from UserRegistration where Email = #Email)
Delete UserProfile where RegID=#tempRegId
RETURN 0
Try this query
DELETE TB1, TB2 FROM TB1 INNER JOIN TB2
WHERE TB1.PersonID = TB2.PersonID and TB1.PersonID = '2'
$qry = "DELETE lg., l. FROM lessons_game lg RIGHT JOIN lessons l ON lg.lesson_id = l.id WHERE l.id = ?";
lessons is Main table and
lessons_game is subtable so Right Join
DELETE TB1, TB2
FROM customer_details
LEFT JOIN customer_booking on TB1.cust_id = TB2.fk_cust_id
WHERE TB1.cust_id = $id
Im working on this large DB which has a lot of the business knowledge embedded in the SPs[I know!] and there is a lot of chaining between the SPs. i.e one stored proc calling another.
Im want to find out a list of stored procedures which update a particular column. How would I do that.
Using showplan_All as outlined in
SQL Table and column Parser for stored procedures doesnt work for me, because this is a shared dev db.
using a Sp from master db scanning system text as described is not feasible because I dont have access to the master db.
So how can I find this informaion?
From system view sys.sql_dependencies you can get dependencies at column level.
DECLARE #Schema SYSNAME
DECLARE #Table SYSNAME
DECLARE #Column SYSNAME
SET #Schema = 'dbo'
SET #Table = 'TableName'
SET #Column = 'ColumnName'
SELECT o.name
FROM sys.sql_dependencies AS d
INNER JOIN sys.all_objects AS o ON o.object_id = d.object_id
INNER JOIN sys.all_objects AS ro ON ro.object_id = d.referenced_major_id
INNER JOIN sys.all_columns AS c ON c.object_id = ro.object_id AND c.column_id = d.referenced_minor_id
WHERE (SCHEMA_NAME(ro.schema_id)=#Schema)
and o.type_desc = 'SQL_STORED_PROCEDURE'
and ro.name = #Table
and c.name = #Column
GROUP BY o.name
Have you tried this : EXEC sp_depends #objname = [table name of the column you are interested in].
So for example, if you had a column named Price in a table named Product, you would execute this: EXEC sp_depends #objname = N'Product'.
Simply executing this would give you list of all sps, views, etc which depend on that particular table.
I use this all the time as I work with a db which has over 400 tables :-)
sp_depends page on MSDN
Try something like this:
use YourDatabase;
select [Name]
from sys.procedures
where object_definition([object_id]) like '%YourColumnName%';
Obviously this has the potential to generate a lot of false positives depending on what the column is named but at least you will have a list of procedures to sift through.
Here's one that works in SQL 2000+; Note that as Andrew noted in his, you will get false positives depending on your column name, but it's a starting place:
SELECT DISTINCT o.Name
FROM syscomments c
JOIN sysobjects o ON c.ID = o.ID
WHERE c.Text LIKE '%ColumnName%'
ORDER BY o.Name
use msdb
go
select * from sysjobs j
inner join sysjobsteps s
on j.job_id=s.job_id
where command like '%HBR_INSTRUMENT%'