I'm using nested cursors to update the first column on every table of my Database, to populate data for an online reporting program.
when testing my cursors using a print statement, everything runs fine. When I switch to the update command, I get an error saying variable #table must be defined. Why does the variable only work for a print, and how can I make this work correctly?
declare #table varchar (30)
declare #Column varchar (30)
DECLARE [TABLE] CURSOR FOR SELECT TABLE_NAME FROM
postfixing.INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' order
by table_name
OPEN [TABLE]
FETCH FROM [TABLE] INTO #TABLE
WHILE ##FETCH_STATUS=0
BEGIN
DECLARE [COLUMN] CURSOR FOR SELECT Top 1 Column_name FROM
postfixing.INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME =#table order by
column_name
OPEN [COLUMN]
FETCH FROM [COLUMN] INTO #COLUMN
WHILE ##FETCH_STATUS=0
BEGIN
PRINT #TABLE+' '+#COLUMN
--UPDATE #TABLE SET #COLUMN=#COLUMN
FETCH FROM [COLUMN] INTO #COLUMN
END
DEALLOCATE [COLUMN]
FETCH FROM [TABLE] INTO #TABLE
END
DEALLOCATE [TABLE]
Well since you are only getting the first row you can eliminate the nested cursor and it should do what you want:
declare #table varchar (30)
declare #Column varchar (30)
DECLARE [TABLE] CURSOR FOR SELECT TABLE_NAME FROM
postfixing.INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' order
by table_name
OPEN [TABLE]
FETCH FROM [TABLE] INTO #TABLE
WHILE ##FETCH_STATUS=0
BEGIN
SET #COLUMN = (SELECT Top 1 Column_name FROM
postfixing.INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME =#table order by
column_name)
PRINT #TABLE+' '+#COLUMN
--UPDATE #TABLE SET #COLUMN=#COLUMN
FETCH FROM [TABLE] INTO #TABLE
END
CLOSE [TABLE]
DEALLOCATE [TABLE]
Related
I have two databases old and new. I want to count record from both the databases and insert into new temporary table with their table name.
I created temporary table:
CREATE TEMPORARY TABLE tempemp (tablename varchar(50),northwindcount int(11),dest_northwindcount int(11));
and counted records:
select (select count(*) from northwind.orders) as northwind_cnt, (select count(*) from dest_northwind.orders) as dest_northwind_cnt;
How can I insert into temp table?
Dunno about MySql, but in MS SqlServer T-SQL, you'd do something like this:
INSERT INTO
Tempemp(
tablename,northwindcount,dest_northwindcount)
SELECT
'???' AS table make,
(SELECT COUNT(*) FROM Northwind.Orders)
AS Northwindcount,
(SELECT COUNT(*) FROM Dest_Northwind.Orders)
AS dest_northwindcount
My syntax might be a little off, but the general idea is that an INSERT statement can have a SELECT clause instead of a VALUES clause. Maybe something similar in MySql?
i write procedure for this and now this is working.
thank you all.
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE newcount INTEGER;
DECLARE oldcount INTEGER;
DECLARE oldtableName char(50);
DECLARE newtableName char(50);
DECLARE curs1 CURSOR FOR SELECT TABLE_NAME,SUM(TABLE_ROWS) as count FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dest_northwind' AND
TABLE_NAME IN(select table_name from information_schema.tables
where table_schema='dest_northwind') GROUP BY TABLE_NAME ;
DECLARE curs2 CURSOR FOR SELECT TABLE_NAME,SUM(TABLE_ROWS) as count FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'northwind' AND
TABLE_NAME IN(select table_name from information_schema.tables
where table_schema='northwind') GROUP BY TABLE_NAME ;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN curs1;
OPEN curs2;
read_loop: LOOP
FETCH curs1 INTO newtableName,newcount;
FETCH curs2 INTO oldtableName,oldcount;
IF done THEN
LEAVE read_loop;
END IF;
SELECT newtableName,newcount,oldcount;
insert into zreult1(Tablename,Northwind,Dest_Northwind)values(oldtableName,oldcount,newcount);
END LOOP;
CLOSE curs1;
CLOSE curs2;
END
I have table with same name (name-xxx) in 100 different schema in same mysql server.
I want to alter all table named xxx by using a single script (without hard coding
the schema name in the script)
You can try something like that:
DECLARE #alterQ NVARCHAR(max)
DECLARE #table_name VARCHAR(45)
DECLARE tables_curs CURSOR FOR
SELECT t.table_name
FROM INFORMATION_SCHEMA.TABLES t
WHERE t.table_name = 'xxx'
AND t.table_catalog = 'db_name'
OPEN tables_curs
FETCH tables_curs INTO #table_name
WHILE ##Fetch_Status = 0
BEGIN
SET #table_name = N'ALTER TABLE #table_name ...'
EXEC sp_executesql #alterQ
END
CLOSE tables_curs
DEALLOCATE tables_curs
I'm reverse-engineering a MySQL database and I'd like to get a list of example values from every column in every table. I'd like to run a query like this:
select
table_name,
column_name,
group_concat(
(select distinct table_name.column_name limit 100)
separator ','
) as examples
from
information_schema.columns
where
table_schema = 'myschema'
;
I'd like the output to look something like this:
table1 column1 (123,124,234)
table1 column2 ('Joe','Sara','Bob')
MySQL won't accept table_name.column_name as valid syntax. What's the right way to write this query?
I think Sam, you are looking for something like that, or at least it would be a better approach:
select
table_name,
column_name,
group_concat((column_name) separator ',') as examples
from
information_schema.columns
where
table_schema = 'test'
GROUP BY table_name
;
Based on rene's suggestion, I wrote a stored procedure which outputs examples of values from each column in every table. It's ugly and slow, but it works. I'd welcome suggestions on how to improve this code.
DELIMITER //
CREATE PROCEDURE column_example_values(
IN db_name VARCHAR(64),
IN tbl VARCHAR(64),
IN col VARCHAR(64),
OUT result MEDIUMTEXT)
BEGIN
SET #s = CONCAT('SELECT GROUP_CONCAT(tbl1.',col,
' separator \',\') FROM (SELECT DISTINCT ',
col,' FROM ',db_name,'.',tbl,
' LIMIT 100) tbl1 INTO #result1');
PREPARE stmt FROM #s;
EXECUTE stmt;
SET result = IFNULL(#result1,'');
END;
//
DELIMITER ;
DELIMITER //
CREATE PROCEDURE all_columns_example_values(IN db_name VARCHAR(64))
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE tbl, col VARCHAR(64);
DECLARE cur1 CURSOR FOR
SELECT
table_name,
column_name
FROM
information_schema.columns
WHERE
table_schema = db_name
ORDER BY
table_name,
column_name;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
CREATE TEMPORARY TABLE results (
tbl VARCHAR(64), col VARCHAR(64), examples MEDIUMTEXT);
OPEN cur1;
read_loop: LOOP
FETCH cur1 INTO tbl, col;
IF done THEN
LEAVE read_loop;
END IF;
CALL column_example_values(db_name,tbl,col,#result);
INSERT INTO results (tbl, col, examples) VALUES (tbl, col, #result);
END LOOP;
CLOSE cur1;
SELECT * FROM results;
DROP TABLE results;
END;
//
DELIMITER ;
It can be called with
CALL all_columns_example_values('mydb');
Is it possible to show the name of a table in a db where a specific value is present. I have different tables and i want to show only the table names that contains a specific value in any of the fields.
This will return lots of empty result sets, but the non-empty ones correspond to table/column combinations that fit your search. It only works for text, and detects columns that contain the value (as opposed to a full column match.)
DELIMITER |
DROP PROCEDURE IF EXISTS `SearchAllTables`|
CREATE PROCEDURE `SearchAllTables` (
IN _search varchar(256)
)
LANGUAGE SQL
DETERMINISTIC
SQL SECURITY DEFINER
BEGIN
-- declare stuff
declare _tableName varchar(64);
declare _columnName varchar(64);
declare _done tinyint(1) default 0;
-- we will examine every string column in the database
declare _columnCursor cursor for
select TABLE_NAME, COLUMN_NAME
from INFORMATION_SCHEMA.COLUMNS
where TABLE_SCHEMA = database()
and (DATA_TYPE like '%char%'
or DATA_TYPE like 'text');
declare CONTINUE handler for NOT FOUND
SET _done = 1;
OPEN _columnCursor;
LOOP1: LOOP
-- get the next table/column combination
FETCH _columnCursor INTO _tableName,_columnName;
IF _done = 1 THEN
CLOSE _columnCursor;
LEAVE LOOP1;
END IF;
-- query the current column to see if it holds the value
SET #query = concat(
"select '",_tableName,"' as TableName, '",
_columnName,"' as ColumnName
from ",_tableName,"
where ",_columnName," like concat('%',?,'%')
group by 1;"
);
SET #search = _search;
PREPARE _stmt FROM #query;
EXECUTE _stmt USING #search;
DEALLOCATE PREPARE _stmt;
END LOOP LOOP1;
END|
DELIMITER ;
Oh, yeah, and it's ugly... Maybe it'll help you, though!
SELECT TABLE_NAME
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'database_name'
AND COLUMN_NAME = 'column_name'
I want to run a diagnostic report on our SQL Server 2008 database server.
I am looping through all of the databases, and then for each database, I want to look at each table. But, when I go to look at each table (with tbl_cursor), it always picks up the tables in the database 'master'.
I think it's because of my tbl_cursor selection :
SELECT table_name FROM information_schema.tables WHERE table_type = 'base table'
How do I fix this?
Here's the entire code:
SET NOCOUNT ON
DECLARE #table_count INT
DECLARE #db_cursor VARCHAR(100)
DECLARE database_cursor CURSOR FOR
SELECT name FROM sys.databases where name<>N'master'
OPEN database_cursor
FETCH NEXT FROM database_cursor INTO #db_cursor
WHILE ##Fetch_status = 0
BEGIN
PRINT #db_cursor
SET #table_count = 0
DECLARE #table_cursor VARCHAR(100)
DECLARE tbl_cursor CURSOR FOR
SELECT table_name FROM information_schema.tables WHERE table_type = 'base table'
OPEN tbl_cursor
FETCH NEXT FROM tbl_cursor INTO #table_cursor
WHILE ##Fetch_status = 0
BEGIN
DECLARE #table_cmd NVARCHAR(255)
SET #table_cmd = N'IF NOT EXISTS( SELECT TOP(1) * FROM ' + #table_cursor + ') PRINT N'' Table ''''' + #table_cursor + ''''' is empty'' '
--PRINT #table_cmd --debug
EXEC sp_executesql #table_cmd
SET #table_count = #table_count + 1
FETCH NEXT FROM tbl_cursor INTO #table_cursor
END
CLOSE tbl_cursor
DEALLOCATE tbl_cursor
PRINT #db_cursor + N' Total Tables : ' + CAST( #table_count as varchar(2) )
PRINT N'' -- print another blank line
SET #table_count = 0
FETCH NEXT FROM database_cursor INTO #db_cursor
END
CLOSE database_cursor
DEALLOCATE database_cursor
SET NOCOUNT OFF
The problem is because you're actually always running the INFORMATION_SCHEMA.TABLES query under the master db context.
You'd need to convert the tbl_cursor block into dynamic SQL in order to fully qualify the query with the DB name.
e.g.
SELECT table_name FROM YourDatabase.INFORMATION_SCHEMA.TABLES WHERE....
is essentially what you need to be executing for that cursor.
It's easier to use table variables so you can add rows to #tablist using another dynamic SQL statement
SET NOCOUNT ON
DECLARE #table_count INT
DECLARE #dblist TABLE (DBName VARCHAR(100))
DECLARE #tablist TABLE (TableName VARCHAR(100))
DECLARE #dbname varchar(100), #tabname varchar(100)
INSERT #dblist
SELECT name FROM sys.databases where name<>N'master'
SELECT TOP 1 #dbname = DBName FROM #dblist
WHILE ##ROWCOUNT <> 0
BEGIN
INSERT #tablist (tableName)
EXEC ('SELECT table_name FROM ' + #dbname + '.information_schema.tables WHERE table_type = ''base table'' ')
SELECT TOP 1 #tabname = tableName FROM #tablist
WHILE ##ROWCOUNT <> 0
BEGIN
--do my stuff
DELETE #tablist WHERE tableName = #tabname
SELECT TOP 1 #tabname = tableName FROM #tablist
END
DELETE #dblist WHERE DBName = #dbname
SELECT TOP 1 #dbname = DBName FROM #dblist
END
You might have to create dynamic SQL. because information_schema will fetch objects only from the current active database against which you are running this query.
you can try sys.objects