SQL: use computed string as table name, join all rows of select for counting - sql

I have access to a MS SQL Server with MS Access via ODBC and I want to display the table names, their column names and the number of rows per table. The table names are stored in a table named "sys_tables", the column names in "sys_columns". Unfornunately the number of rows per table has to be counted. As I'm not experienced in SQL, my first try is not working:
SELECT t.name, c.name, t.object_id, x.cnt
FROM sys_tables AS t INNER JOIN sys_columns AS c ON t.object_id = c.object_id
LEFT OUTER JOIN (SELECT COUNT(*) AS cnt FROM #t.name AS tbl ON tbl.cnt > 0) AS x
What is the right way to use a computed string in a SELECT as table name? Can I do a sub select that selects all rows without real relation?

You can't use a variable table name in a SQL statement on the server side. You will need to get the table names from SQL Server and then use those to send new queries (one for each table) back to SQL Server. You could also write a stored procedure on the SQL Server to handle this using dynamic SQL (just be sure that you are familiar with injection attacks whenever you are using dynamic SQL).
SQL Server stores some row count information in sysindexes (not to be confused with sys.indexes) in the rowcnt column. This information is not always 100% accurate though.
Finally, you can use the undocumented stored procedure sp_MSForEachTable like so:
EXEC sp_msForEachTable
'SELECT PARSENAME(''?'', 1),
COUNT(*) FROM ?'
Be aware that this last method will return multiple result sets (one for each table), so you need to handle it that way in Access or combine them together in a temporary table and then return them as one result set. You can do all of that in a stored procedure.

You cannot use a variable for a table name. The only workaround is dynamic SQL.
However, I suspect that there's a table somewhere in sys which gives the row count for each table, though it may not be kept perfectly up-to-date.

Can't you do this:
SELECT COUNT(t.name)
FROM sys_tables AS t INNER JOIN sys_columns AS c ON t.object_id = c.object_id

Related

Sql to update column values with values from other columns for multiple tables

I have multiple tables containing columns 'Name' and 'NameEN'.
I need to update column 'NameEN' with values form column 'Name'
I know how to update single tables with
Update Table
set NameEN = Name
and I know how to get the list of tables containing the column 'NameEN'
SELECT c.name AS 'ColumnName'
,t.name AS 'TableName'
FROM sys.columns c
JOIN sys.tables t ON c.object_id = t.object_id
WHERE c.name LIKE '%NameEN%'
ORDER BY TableName
,ColumnName;
Can I somehow combine the 2 queries to update all tables that contain the column 'NameEN'?
I'm using mssms and the server is running ms sql server 14.0.1 if that's important.
You can use the command EXECUTE sp_executesql:
You can find example on link: https://learn.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-executesql-transact-sql?view=sql-server-ver15
You can build a sql statement by the system table query to find the tables you need to update and then feed the results to the sp_executesql function. You can either use a cursor to loop through the results or just copy the resulting statements into code editor and run it manually.

Get current table name in query

Is it possible to get table name in select statement?
Example:
SELECT Id, "Users" as TableName
FROM Users
I don't want to write "Users" manually but to determine it based on FROM statement.
I'm doing some migrations from one database to another (with different structure), and I have mapping table that stores old table names so that's why I need this (it's less error prone).
You can use following sub-query to get this information (works on SQL Server 2012+):
SELECT *,
(select object_name(ind.object_id)
from sys.fn_PhysLocCracker(%%physloc%%) plc
INNER JOIN SYS.DM_DB_DATABASE_PAGE_ALLOCATIONS(DB_ID(),null,null,null,null) ind
ON ind.allocated_page_file_id = plc.file_id
AND ind.allocated_page_page_id = plc.page_id) as table_name
FROM [your table]
It is painfully slow, caching on the side page allocation will speed things up.
Alternatively, if you want to do it for all tables, you can use following stored procedure:
USE [DB_NAME]
EXEC sp_msforeachtable 'SELECT Id, ''?'' AS [TableName] FROM ?'
Maybe it will be helpful for somebody :)

Using table variables in Oracle Stored Procedure

I have lots of experience with T-SQL (MS SQL Server).
There it is quite common to first select some set of records into a
table variable or say temp table t, and then work with this t
throughout the whole SP body using it just like a regular table
(for JOINS, sub-queries, etc.).
Now I am trying the same thing in Oracle but it's a pain.
I get errors all the way and it keeps saying
that it does not recognize my table (i.e. my table variable).
Error(28,7): PL/SQL: SQL Statement ignored
Error(30,28): PL/SQL: ORA-00942: table or view does not exist
I start thinking what at all is possible to do with this
table variable and what not (in the SP body) ?
I have this declaration:
TYPE V_CAMPAIGN_TYPE IS TABLE OF V_CAMPAIGN%ROWTYPE;
tc V_CAMPAIGN_TYPE;
What on Earth can I do with this tc now in my SP?!
This is what I am trying to do in the body of the SP.
UPDATE ( SELECT t1.STATUS_ID, t2.CAMPAIGN_ID
FROM V_CAMPAIGN t1
INNER JOIN tc t2 ON t1.CAMPAIGN_ID = t2.CAMPAIGN_ID
) z
SET z.STATUS_ID = 4;
V_CAMPAIGN is a DB view, tc is my table variable
Presumably you are trying to update a subset of the V_CAMPAIGN records.
While in SQLServer it may be useful to define a 'temporary' table containing the subset and then operate on that it isn't necessary in Oracle.
Simply update the table with the where clause you would have used to define the temp table.
E.g.
UPDATE v_campaign z
SET z.status_id = 4
WHERE z.column_name = 'a value'
AND z.status <> 4
I assume that the technique you are familiar with is to minimise the effect of read locks that are taken while selecting the data.
Oracle uses a different locking strategy so the technique is mostly unnecessary.
Echoing a comment above - tell us what you want to achieve in Oracle and you will get suggestions for the best way forward.

SQL Server 2008 - SELECT query

I have a database with over a 150 tables. I need to be able to find every table that has a column called EmployeeID. Is there a way for me to find all tables that have this column? It's kind of a long process if I go through each table and try to find if it has that column.
Use INFORMATION_SCHEMA.COLUMNS:
select c.*
from INFORMATION_SCHEMA.COLUMNS c
where column_name = 'EmployeeID';

How can I turn a column name into a result value in SQL Server?

I have a table which has essentially boolean values in a legacy database. The column names are stored as string values in another table so I need to match the column names of one table to a string value in another table. I know there has to be a way to do this directly with SQL in SQL Server but it is beyond me.
My initial thought was to use PIVOT but it is not enabled by default and enabling it would likely be a difficult process with pushing that change to the Production database. I would prefer to use what is enabled by default.
I am considering using COALESCE to translate the boolean value to the string that value that I need. This will be a manual process.
I think I will also use a table variable to insert the results of the first query into that variable and use those results to do the second query. I still have the problem that the columns are on a single row so I wish I could easily pivot the values to put the column names in the result set as strings. But if I could easily do that I could easily write the query with a sub-select.
Any tips are welcome.
Checkout Sysobjects and SysColumns in SQL Server. They are 2 SQL tables that gives you the names of the tables in your DB and the names of the columns that go with that table.
The system view INFORMATION_SCHEMA.COLUMNS will also give you what you want.
You can build a SQL string and then execute that string as a query. Not the prettiest by any means but I think it would work the way you want it to. You would just use a cursor or while loop to build the string.
If you're comfortable with .Net you could just write your own stored proc in your language of choice and manipulate the data in code instead.
Heres a link to get started
CLR Stored Procedures
I'm not quite sure I understand how your design is currently put together (could you post an example?), but the information_schema.columns view will give you a table containing all the column names as string values. If you join your second table against that I think you'll probably get what you need.
For Example, i have a table STATEtbl having 3 columns and i want to get all the column names of this table as ROW values... i use the below query
Select SC.name as Columns from Syscolumns SC
Join Sysobjects SO On SC.id = SO.Id
where Object_name(SO.Id) = 'STATEtbl'
Result of the query:
Columns
--------
State
StateCode
StateFullName