Hello good day everyone.
I have a table design in SQL server that looks like this:
NAME AGE WORK BIRTH
TEST 21 NONE 12/12/2000
In this table, I have created a trigger upon updating table and would save the data to audit log table. This audit log table holds the value being updated and the columns that has been update. I have a query snippet here that gets the columns that has been updated. I also get this query her on stack.
DECLARE #idTable INT
SELECT #idTable = T.id
FROM sysobjects P JOIN sysobjects T ON P.parent_obj = T.id
WHERE P.id = ##procid
-- Get COLUMNS_UPDATED if update
--
DECLARE #Columns_Updated VARCHAR(50)
SELECT #Columns_Updated = ISNULL(#Columns_Updated + ', ', '') + name
FROM syscolumns
WHERE id = #idTable
AND CONVERT(VARBINARY,REVERSE(COLUMNS_UPDATED())) & POWER(CONVERT(BIGINT, 2), colorder - 1) > 0
Now my audit log table looks like this:
OLD NEW COLUMNS_UPDATED
tEST,21,NONE TEST2,20,TEACHER AGE,NAME,WORK
Now my problem is, how I can sort the columns updated that looks like also the design table. My preferred output should look like this.
OLD NEW COLUMNS_UPDATED
tEST,21,NONE TEST2,20,TEACHER NAME,AGE,WORK
I hope anyone could help me with this.
Thanks.
Try:
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'myTable'
ORDER BY ORDINAL_POSITION
Related
I have table which has basically 2 rows containing the name of failure and the main table i want to write a query such that
Select main
from xyz
will return the table name like abc.
Now I want to get the data from the abc table
Select *
from
(select main
from xyz)
which returns abc.
How can I write it ?
You must use dynamic sql.
Note, that you can't use "SELECT to nowhere" in a compound statement in Db2. That is, the following code is erroneous.
BEGIN
SELECT * FROM MYTAB;
END#
This is why you need to store the result of SELECT somewhere. You may use Global Temporary Tables for that presuming, that USER TEMPORARY TABLESPASE is available to use for your user.
--#SET TERMINATOR #
BEGIN
DECLARE V_STMT VARCHAR (500);
SELECT
'DECLARE GLOBAL TEMPORARY TABLE SESSION.RESULT'
|| ' AS (SELECT * FROM '
|| MAIN
|| ') WITH DATA WITH REPLACE '
|| 'ON COMMIT PRESERVE ROWS NOT LOOGED'
INTO V_STMT
FROM XYZ
-- place your WHERE clause here if needed
FETCH FIRST 1 ROW ONLY
;
EXECUTE IMMEDIATE V_STMT;
END
#
SELECT * FROM SESSION.RESULT
#
dbfiddle link.
Here is a solution on stack that shows how to get the table names from your database
DB2 Query to retrieve all table names for a given schema
Then you could take your failure table and join into it based off of the table name, that should match your errors to the table that match on the table name. I'm not a 100% sure of your question but I think this is what you are asking.
The inner system query has schema and name. Type is T for table. See IBM link below for column reference. You could run the query wide open in the inner query to look for the tables you want. I would recommend using schema to isolate your search.
https://www.ibm.com/docs/en/db2-for-zos/11?topic=tables-systables
SELECT
ft.*
, st.*
FROM [FailureTable] as ft
INNER JOIN
(
select * from sysibm.systables
where CREATOR = 'SCHEMA'
and name like '%CUR%'
and type = 'T'
) st
ON st.[name] = ft.[tablename]
You can try
DECLARE #tableName VARCHAR(50);
SELECT #tableName = main
FROM xyx
EXEC('SELECT * FROM ' + 'dbo.' + #tableName)
Dont forget to add validation if #tableName doesnt get populated
I have 2 tables corporate and corporate_copy. Initially they were same in structure but people started added new columns into corporate and forgot do do so for corporate_copy.
Somewhere in the application there is less used functionality that copies data from corporate to corporate_copy and that kept failing without anyone noticing. Now I have to add 28 columns (ofcourse with same type and length and constraints etc....).
I know it can be done in one ALTER TABLE statement but I still feel it is lengthy task.
Do we have any luxury that will make copy table same as main table by keeping data and adding default values in newly added columns?
I am asking much but is there anything like that?
--Generate a dynamic query which contain all the missing column list and Execute it
--for eg I tried Something
BEGIN TRAN
DECLARE #SqlSelect NVARCHAR(MAX),#ColumnDeclaration VARCHAR(2000)
SELECT DISTINCT ' '+COLUMN_NAME+' '+ DATA_TYPE +' '+ISNULL(CONVERT(NVARCHAR(10), CHARACTER_MAXIMUM_LENGTH ),'')+' 'Missing_Column INTO #T FROM INFORMATION_SCHEMA.COLUMNS a
WHERE a.column_name not in (SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS b
WHERE b.table_name in ('Corporate_Copy'))
and a.table_name in ('Corporate')
SELECT #ColumnDeclaration=STUFF((
SELECT ', ' + Missing_Column
FROM #T
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(max)'), 1, 1, '')
SET #SqlSelect=' ALTER TABLE Corporate_Copy Add'+ #ColumnDeclaration + ');'
PRINT #SqlSelect
ROLLBACK TRAN
You could use schema compare, found in SQL Server data tools (free) to generate a change script automatically.
But if this is just a copy, you could just run this:
DROP TABLE Corporate_Copy;
SELECT *
INTO Corporate_Copy
FROM Corporate;
It's not clear whether you really need to preserve the data in the copy. If so, it's not really a copy is it?
From SQL-Server 2015, you can use the following query to extract all different columns between 2 tables:
select distinct a.* from INFORMATION_SCHEMA.COLUMNS a
where a.column_name not in (select column_name from INFORMATION_SCHEMA.COLUMNS b
where b.table_name in ('tbl_A'))
and a.table_name in ('tbl_B')
order by a.column_name
The output gives you enough information to create a simple script to add the columns which are missing:
For exmaple:
Alter table tbl_A ADD res.Column_Name res.Data_Type ....
generate CREATE script in SSMS (right-click on table, then "script table as...")
Delete all things that already exists. Usually they are in the begining and it's a simple
change CREATE to ALTER ... ADD
That should be possible using SELECT INTO, for example the following SQL statement creates a backup copy of corporate:
SELECT * INTO corporate_copy
FROM corporate ;
I have around 500 tables in my database and each table is having a minimum of 100 columns.We total 5 person are working in the same database.So whenever requirement arises then a new column or a table is added.What ever I make changes,I keep a record but my colleagues didnt do it.So I am facing problem now what others have created column in the existing table or a new table is created.
So can anybody please tell me is it possible to know whether a new column is added to an existing table and if added what is the column name?
May be this query help you
SELECT
t.name AS table_name,
SCHEMA_NAME(schema_id) AS schema_name,
c.name AS column_name,
modify_date, create_date
FROM
sys.tables AS t
INNER JOIN
sys.columns c ON t.OBJECT_ID = c.OBJECT_ID
ORDER BY
modify_date DESC
EDIT
To Audit this, You have to use DDL trigger
Step 1:- Create New Audit Table
CREATE TABLE DDLAudit
(
PostTime datetime, DatabaseName varchar(256), Event nvarchar(100),
ObjectName varchar(256), TSQL nvarchar(2000), Login varchar(256)
)
Step 2:- Create DDL Trigger
CREATE TRIGGER AuditChanges
ON DATABASE
FOR CREATE_TABLE, ALTER_TABLE, DROP_TABLE
AS
DECLARE #ed XML
SET #ed = EVENTDATA()
INSERT INTO DDLAudit (PostTime, DatabaseName, Event, ObjectName, TSQL, Login)
VALUES
(
GetDate(),
#ed.value('(/EVENT_INSTANCE/DatabaseName)[1]', 'varchar(256)'),
#ed.value('(/EVENT_INSTANCE/EventType)[1]', 'nvarchar(100)'),
#ed.value('(/EVENT_INSTANCE/ObjectName)[1]', 'varchar(256)'),
#ed.value('(/EVENT_INSTANCE/TSQLCommand)[1]', 'nvarchar(2000)'),
#ed.value('(/EVENT_INSTANCE/LoginName)[1]', 'varchar(256)')
)
Now, Every Changes will be logged in Your DDLAudit. You can Filter out based on datetime filter on PostTime column.
Using the below query you can find the tables which were altered recently.
Query to know the table last altered
SELECT * FROM sys.tables
order by modify_date desc
Query to know the Column altered
SELECT TOP (select count(distinct(TransactionID))
from ::fn_trace_gettable( LEFT((select path from sys.traces where is_default = 1 ),len((select path from sys.traces where is_default = 1 )) - PATINDEX('%\%', reverse((select path from sys.traces where is_default = 1 )))) + '\log.trc', default )
where EventClass in (46,47,164) and EventSubclass = 0 and
DatabaseID <> 2 and
ObjectName='table1' and StartTime>'2015-01-10 00:00:00') [name],[colorder]
FROM [sys].[syscolumns]
where id=(SELECT object_id FROM sys.tables
where name='table1')
order by colorder desc
Note: this query will not work if there was any column dropped or the multiple columns of the table was altered using the SQL server UI but will keep track of multiple alter in the same query
The dropped column can be identified by the colorder. You will find the order will be missing but the column information you will not be able to see.
If you provide the table name and the date time, it gives the columns which were altered with order.
If it doesnt return any value then it means there was no change made on the table.
One row in a table got mistakenly overwritten. I have a backup of the table and need to update a single row in the main table with the backup data. The trouble is that the table has almost 100 columns. Is there an easy way to do this in SQL Server so that I do not have to manually write out this:
set maintable.a = backuptable.a,
maintable.b = backuptable.b,......etc.
all the way up to the 100th column. I would think that SQL Server Management Studio could know that I want to update the fields with the same-named fields in the other table. Is there a way to do this?
Thanks in advance.
INSERT INTO MainTable
SELECT *
FROM BackUpTable
WHERE RowID = GoodRow
DELETE FROM MainTable
WHERE RowId = BadRow
Just insert the "good" row and delete the "bad" row.
If there is a PK constraint you can delete/insert in the opposite order.
It would also be wise to enclose this in a TRANSACTION.
In SSMS you can drag-n-drop the columns node in the Object Explorer to the Query window. It will generate a comma-separated string of all the columns.
> declare #aa varchar (max) set #aa = ''
>
> select #aa =
> (case when #aa = ''
> then column_name
> else #aa + coalesce(', ' + column_name+'= '+column_name, '')
> end) from amicus.INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'People' print #aa
How can I Select all columns from all tables from the DB, like:
Select * From *
in SQL Server 2008???
The table list it´s very very big, and have so many columns, is it possible to do it without writing the column names?
Or maybe make a select that returns the name of the tables.
This SQL will do this...
DECLARE #SQL AS VarChar(MAX)
SET #SQL = ''
SELECT #SQL = #SQL + 'SELECT * FROM ' + TABLE_SCHEMA + '.[' + TABLE_NAME + ']' + CHAR(13)
FROM INFORMATION_SCHEMA.TABLES
EXEC (#SQL)
Try this, works fine
SELECT * FROM INFORMATION_SCHEMA.COLUMNS
then you could add
WHERE TABLE_NAME LIKE '' AND COLUMN_NAME LIKE ''
SELECT t.name AS table_name,
SCHEMA_NAME(schema_id) AS schema_name,
c.name AS column_name
FROM sys.tables AS t
INNER JOIN sys.columns c ON t.OBJECT_ID = c.OBJECT_ID where t.name = 'ProductItem' AND C.name like '%retail%'
ORDER BY schema_name, table_name
It is possible to retrieve the name of all columns from sys.columns
It is possible to retrieve the name of all table from sys.tables
But is impossible to retrieve all the data from all the tables. As soon as more than one table is involved in a query, a JOIN is necessary. Unless join conditions are provided, tables are joined as full Cartesian product, meaning each row from each table is matched with each row from ll other tables. Such a query as you request would produce for 10 tables with 10 records each no less than 10e10 records, ie. 100 billion records. I'm sure you don't want this.
Perhaps if you explain what you what to achieve, not how, we can help better.
To select * from each table, one after another, you can use the undocumented but well known sp_msforeachtable:
sp_msforeachtable 'select * from ?'
If you are going to send to Excel, I would suggest you use the export wizard and simply select all the tables there. In the object browser, put your cursor on the database name and right click. Chose Tasks - Export Data and follow the wizard. WHy anyone would want an entire database in Excel is beyond me, but that's the best way. If you need to do it more than once you can save the export in an SSIS package.
In SQL Server 2016 Management Studio ( Version: 13.0.15900.1), to get all column names in a specified table, below is the syntax:
**Select name from [YourDatabaseName].[sys].[all_columns]
where object_id=(Select object_id from [YourDatabaseName].[sys].[tables]
where name='YourTableName')**