Simple query for generating database metrics? - sql

Give a database (Sybase) with many tables, I would like to write a SQL query that will calculate, for each table, the number of rows and the number of columns.
Unfortunately, my SQL is a bit rusty. I can generate the table names:
select name from sysobjects where type = 'U'
but how to bind the databases returned to T in:
select count(*) from T
is beyond me. Is it even possible to do this kind of thing?

I don't use Sybase, but the online docs indicate the row counts are in systabstats and the columns are in syscolumns.
SELECT sysobjects.name,
(SELECT COUNT(*) FROM syscolumns WHERE syscolumns.id = sysobjects.id) AS cols,
systabstats.rowcnt
FROM sysobjects
JOIN systabstats
ON (sysobjects.id = systabstats.id AND sysobjects.type = 'U' AND systabstats.indid = 0)

As fredt has given the answer, I'll just provide some extra info.
The built in procedure sp_spaceused "tablename" will give you the number of rows for a selected table, along with details of how much storage space it's using. Used without the parameter it provides storage usage for the current database as a whole.
You can look at the SQL in the various system stored procedures to see where they get their information from. sp_spaceused and sp_help would both be useful for you in this. They live in the sybsystemprocs database. Just be careful not to modify any of those procedures.
There are various versions of a stored procedure called sp_rowcount floating around the internet, that provide what you ask for (rowcount anyway), but inside they are equivalent to the select statement from fredt. The one I use provides index count and table locking scheme. I don't recall exactly where I got mine so don't want to just distribute it in case I upset someone's copyright.

Related

Join two result sets on different databases in SQL Server

May be this question is redundant but I am posting it as I could not get an exact solution (Please read Actual Scenario).
I have the following script which returns all the tables and corresponding no. of rows.
SELECT
sysobjects.Name, sysindexes.Rows
FROM
sysobjects
INNER JOIN sysindexes
ON sysobjects.id = sysindexes.id
WHERE
type = 'U'
AND sysindexes.IndId < 2 ORDER BY ([Rows])
Now, I want to join this result set with similar result set on a different database (with same structure). I am not able to use four partition naming with sysobjects. It gives error: The multi-part identifier "My_Database1.sysobjects.Name" could not be bound.
Actual Scenario: I have a duplicate database and want to know in which tables data has not been moved from original database.
Any alternate solution would also help.
put .dbo between "My_Database1. and sysobjects.Name" as in
My_Database1.dbo.sysobjects
you should be ble to query sys tables on different database than the one you are connected (as long as they are on the same instance, of course). Check your sysntax, I believe you are missing the schema name sys so it would be:
SELECT * FROM My_Database1.sys.sysobjects
Please use sys object for system data table:
select sys_obj.* from DatabaseName.Sys.sysobjects sys_obj

Find Informix table and column details using SQL query

I want to get Informix database table information and column information such as
table names
column names of the table
data types of the columns
data type length (ex: if column is varchar)
constraints on the columns
I am able to find the table names and column names using this query to get the table names:
select tabname from systables
to find the column name
SELECT TRIM(c.colname) AS table_dot_column
FROM "informix".systables AS t, "informix".syscolumns AS c
WHERE t.tabname = 'agent_status'
AND t.tabtype = 'T'
and t.tabid = c.tabid
AND t.tabid >= 100 ;
but I am not able to find the data types and constraints on the columns.
Can anyone tell me the SQL query to get the total details of the table mentioned above?
Wow! That's a complex query - best treated as at least two, probably three queries; or maybe that's what you had in mind anyway.
You might want to select tabid and owner in the first query, and it is good form to use "informix".systables rather than just systables (though that only really matters in a MODE ANSI database, but then it really does matter).
The query on syscolumns is fine, though the t.tabid >= 100 clause is probably redundant, unless you definitively want to prevent people learning about the columns in system catalog tables. Also, it can be helpful to know about the columns in a view, so the tabtype = 'T' might be too stringent.
Decoding the data types is fiddly. For the built-in types, it is not too difficult; for user defined types, it is considerably harder work. The coltype and collength (and extended_d) tell you about the type. You can find C code to translate the basic types in my SQLCMD package, in sqltypes.ec. You can find some simple SQL (that may not be complete) in $INFORMIXDIR/etc/xpg4_is.sql.
Constraint information is stored in sysconstraints and related tables. You can find code for some constraints in the SQLCMD source already mentioned (file sqlinfo.ec).

Most efficient way to store queries and counts of large SQL data

I have a SQL Server database with a large amount of data (65 million rows mostly of text, 8Gb total). The data gets changed only once per week. I have an ASP.NET web application that will run several SQL queries on this data that will count the number of rows satisfying various conditions. Since the data gets changed only once per week, what is the most efficient way to store both the SQL queries and their counts for the week? Should I store it in the database or in the application?
If the data is only modified once a week, as part of and at the end of that (ETL?) process, perform your "basic" counts and store the results in a table in the database. Thereafter, rather than lengthy queries on the big tables, you can just query those small summary tables.
If you do not need 100% up-to-the-minute accurate row counts, you could query SQL Server's internal info:
Select so.name as 'TableName', si.rowcnt as 'RowCount'
from sysobjects so
inner join sysindexes si on so.id = si.id
where so.type = 'u' and indid < 2
Very quick to execute and no extra tables required. Not accurate where many updates are occurring but might be accurate enough in your intended usage. [Thank you to commenters!]
Update: did a bit of digging and this does produce accurate counts (slower due to the sum, but still quick):
SELECT OBJECT_SCHEMA_NAME(ps.object_id) AS SchemaName,
OBJECT_NAME(ps.object_id) AS ObjectName,
SUM(ps.row_count) AS row_count
FROM sys.dm_db_partition_stats ps
JOIN sys.indexes i ON i.object_id = ps.object_id
AND i.index_id = ps.index_id
WHERE i.type_desc IN ('CLUSTERED','HEAP')
AND OBJECT_SCHEMA_NAME(ps.object_id) <> 'sys'
GROUP BY ps.object_id
ORDER BY OBJECT_NAME(ps.object_id), OBJECT_SCHEMA_NAME(ps.object_id)
Ref.
Remember that the stored count information was not always 100%
accurate in SQL Server 2000. For a new table created on 2005 the
counts will be accurate. But for a table that existed in 2000 and now
resides on 2005 through a restore or update, you need to run (only
once after the move to 2005) either sp_spaceused #updateusage =
N'true' or DBCC UPDATEUSAGE with the COUNT_ROWS option.
The queries should be stored as stored procedures or views, depending on complexity.
For your situation I would look into indexed views.
They let you both store a query AND the result set for things like aggregation that otherwise cannot be indexed.
As a bonus, the query optimizer "knows" it has this data as well, so if you check for a count or something else stored in the view index in another query (even one not referencing the view directly) it can still use that stored data.

SQL Server New column added to table but problems with Select *

Morning,
I have a stored procedure that returns 'SELECT *' from a table.
Whenever I add a new column to the table, the 'SELECT *' often returns some data in the wrong columns.
Is this an optimization or caching problem? How do I solve this without having to explicitly define the return column names in my stored procedure?
Thanks!
Regardless of the exact nature of your problem, or a solution to it, I would recommend that you don't use Select * From Table. This is less efficient - each time you run the query, an extra request is sent to the DB to determine exactly what columns '*' constitutes, and then a proper request is sent with specific column information.
The reason for your problem probably depends on the client stack you're using.
Speaking in very general terms, SQL Server will return the columns in the order they're added to the table if you perform a SELECT *. If there is more than one table involved in the query, it will return the columns from each table in the order they appear in the query.
Neither caching nor optimisation should affect this server-side if the table columns have changed, so it may be something happening between your code and the server, in whatever data access stack you happen to be using.
This is one of the reasons it's generally recommended not to use "SELECT *" in client code.
The best way to avoid this problem is to have the stored procedure return a predefined set of columns (SELECT a, b instead of SELECT *) and use a table join to retrieve the rest of the code. Because stored procedures cannot be part of a query, you could refactor the stored procedure into a table-valued user-defined function and perform a join on it:
SELECT f.a, f.b, t.*
FROM dbo.fn_YourFunction('a', 'b') f
INNER JOIN YourTable t ON f.id = t.id

SQL Server: Need to find the origin of a particular string value

Is there a way I can search for a particular string value in a SQL SERVER 2005 database? I have this image path value that I want to modify and I think it's stored in the database.
Also - is there a way that I can search for a column's name for any table in a database? Likewise, search for a tables name in a database?
SELECT B.*
FROM information_schema.COLUMNS B
WHERE table_name
IN (SELECT A.TABLE_NAME FROM information_schema.Tables A WHERE TABLE_TYPE='BASE TABLE')
AND B.COLUMN_NAME LIKE '%yoursearchstring%'
Use this to get a list of all of the tables in a database.
SELECT *
FROM information_schema.Tables
Ust this to get a list of all of the columns in a table
SELECT column_name 'Column Name'
FROM information_schema.columns
WHERE table_name = MyTableName
You can use these together to search through every table and column to search for your string.
There may exist utilities which drill down the catalog/schema of a given server/database and use this info to search for a given match (or partial match) with a given pattern in all the text-like columns. You could possibly even write such a utility and introduce heuristics of your own (say not to search tables which have more than 10,000 rows because you expect the info to be a "configuration-type" table etc.)
An easier way may be to use SQL-Profiler to record every query sent to server (possibly filtered by IP address, by session id etc..). By then running the underlying application so that it would produce the particular string, you'll have a [hopefully] short list of queries, one of which targets the particular table / column where the path/string or parts therefore gets queried from.
Sometimes folks do this with dynamic sql to search across every column in the database. It won't perform all that well, but for a one-off search like this can be quite handy. A quick google search turned up this example - http://codesnippets.joyent.com/posts/show/2157
This is a pretty poor example since it queries each table N times where N is the number of columns (it should just do one table scan instead of N), but it might get the job done. You may also want to not limit to the first 100 chars like that example does.