Replicate SQL row with same data but not defining all columns - sql

Is it possible to do a SQL query where I can take let's say all columns form the row for user 'A' and copy them into row for user 'B' without defining the column names.
For an Example, this will not be against speed or intense data, but to help these tasks be functional instead of doing them redundantly over and over. The params for base user and target user would be the stored procedure params.
Declare #BaseUserId varchar(50),
#TargetUserId varchar(50),
#ColumnName varchar(100)
Declare columnNameCursor Cursor For SELECT c.name
FROM sys.columns c
WHERE c.object_id = OBJECT_ID('dbo.EmployeeMenuAccess')
--Opens the cursor now for loop reading
Open columnNameCursor
Fetch next From columnNameCursor into #ColumnName
While ##Fetch_Status=0 Begin
update DocSS set #ColumnName = (select #ColumnName from DocSS where
Username = #BaseUserId) where Username = #TargetUserID
Fetch next From c into #ColumnName
End
Close columnNameCursor
Deallocate columnNameCursor
Thanks in advance.

CREATE TABLE Test
(id int, name char(10))
;
INSERT INTO Test VALUES(1, 'first');
INSERT INTO Test VALUES(2, 'second');
BEGIN TRAN T1;
SELECT * INTO Temp FROM Test WHERE id = 1;
UPDATE Temp SET id = (SELECT MAX(id)+1 FROM Test);
INSERT INTO Test SELECT * FROM Temp;
DROP TABLE Temp;
COMMIT TRAN T1;
SELECT * FROM Test;
Try this

Related

Stored procedure inside a trigger for logging

I am using an identical trigger for multiple tables for logging DML events and because of that I have lots of redundant code. How can I write a stored procedure and call it inside those triggers to log data?
Here is what my trigger looks like
CREATE OR ALTER TRIGGER [Person].tr_logInsertDeleteOrUpdateemployee
ON [Person].employee
AFTER INSERT, UPDATE, DELETE
AS
BEGIN
SET NOCOUNT ON
DECLARE #tableName varchar(100) = '[Person].employee'
IF EXISTS (SELECT TOP 1 * FROM inserted)
AND EXISTS (SELECT TOP 1 * FROM Deleted)
BEGIN
INSERT INTO dbo.DMLLogs
SELECT updatedRecord = 'updated row', #tableName, ID, SYSTEM_USER, GETDATE()
FROM deleted
END
IF EXISTS (SELECT TOP 1 * FROM inserted)
AND NOT EXISTS (SELECT TOP 1 * FROM Deleted)
BEGIN
INSERT INTO dbo.DMLLogs
SELECT insertedRecord = 'inserted', #tableName, ID, SYSTEM_USER, GETDATE()
FROM inserted
END
IF EXISTS (SELECT TOP 1 * FROM deleted)
AND NOT EXISTS (SELECT TOP 1 * FROM inserted)
BEGIN
INSERT INTO dbo.DMLLogs
SELECT deletedRecord = 'deleted from', #tableName, ID, SYSTEM_USER, GETDATE()
FROM deleted
END
END
Putting aside the question of whether there's a better option than creating triggers, the inserted and deleted virtual tables are not visible in a stored procedure, so there's not really a way to do that. The usual practice here is to automate the creation of the boilerplate triggers so they are all created from a single template. Something like:
create schema admin
go
create or alter proc admin.GenerateAuditingTriggers
as
begin
declare c cursor local for
select name, schema_name(schema_id)
from sys.tables
where schema_id in (schema_id('dbo'))
open c
declare #tableName sysname
declare #schemaName sysname
fetch next from c into #tableName, #schemaName
while ##FETCH_STATUS = 0
begin
declare #sql nvarchar(max) = concat(
'
CREATE OR ALTER TRIGGER ',quotename(#schemaName),'.',quotename('tr_logInsert' + #tableName),'
ON ',quotename(#schemaName),'.',quotename(#tableName),'
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON
DECLARE #tableName varchar(100) = ''',quotename(#schemaName),'.',quotename(#tableName),'''
INSERT INTO dbo.DMLLogs
SELECT updatedRecord = ''inserted row'', #tableName, ID, SYSTEM_USER, GETDATE()
FROM inserted
END
')
print #sql
exec (#sql)
print 'trigger created'
print ''
fetch next from c into #tableName, #schemaName
end
close c
deallocate c
end

How to insert result of Stored Procedure into Temp Table without declaring Temp Table Columns

I want to insert the values of stored procedure into a temp table without predefining the columns for the temp table.
Insert Into #Temp1 Exec dbo.sp_GetAllData #Name = 'Jason'.
How can I do this ? I saw an option as below but can I do it without mentioning the server name ?
SELECT * INTO #TestTableT FROM OPENROWSET('SQLNCLI', 'Server=localhost;Trusted_Connection=yes;',
'EXEC tempdb.dbo.GetDBNames')
-- Select Table
SELECT *
FROM #TestTableT;
I could not find a possible solution without defining temp table schema and writing server name. So, I changed the code and the queries to handle with only known schema. Code example is as below
CREATE TABLE #TestTable ([name] NVARCHAR(256), [database_ID] INT);
INSERT INTO #TestTable
EXEC GetDBNames
SELECT * FROM #TestTable;
As provided in the link https://blog.sqlauthority.com/2013/05/27/sql-server-how-to-insert-data-from-stored-procedure-to-table-2-different-methods/
No-one said it had to be pretty:
CREATE PROCEDURE p AS
SELECT 1 as x, 2 as y, 3 as z
GO
DECLARE c CURSOR FOR
SELECT
name, system_type_name
FROM sys.dm_exec_describe_first_result_set_for_object(OBJECT_ID('p'), 0);
DECLARE #name sysname, #type sysname;
CREATE TABLE #t(fake int)
OPEN c
FETCH NEXT from c into #name, #type
WHILE (##FETCH_STATUS = 0)
BEGIN
EXEC ('ALTER TABLE #t ADD ' + #name + ' ' + #type)
FETCH NEXT from c into #name, #type
END
CLOSE C
DEALLOCATE c
ALTER TABLE #t DROP COLUMN fake;
INSERT INTO #t EXEC p;
GO

T-SQL: Update temp table using "from variable" query

I have a linked server connecting to a Lotus notes database as the source. The destination will be an MS SQL database.
I have two temp tables. The first temp table is pulling in the table names from a linked server. From there, I want to do a record count for each table and store that value into the second temp table beside the table name.
I am having trouble trying to run a loop or cursor for each table name and then updating the second temp table with the record count for each table name.
Right now I am getting an error "Incorrect syntax near 'Execute'". SET record_count = Execute(#sqlCommand)
Declare #DB_tables table (
table_cat varchar(1500),
table_schem varchar(1500),
table_name varchar(1500),
table_type varchar(1500),
remarks varchar(1500)
)
Declare #temp_table table (
table_name varchar(1500),
record_count varchar(255),
drop_script varchar(1500),
update_script varchar(1500)
)
--Load Initial data from linked server database
insert into #DB_Tables
exec sp_tables_ex [LINKED_SERVER_DB]
--Load table name from Stored Procedure
INSERT INTO #temp_table (table_name)
SELECT table_name from #DB_Tables
--select * from #temp_table
--Variable to hold each table name in a loop or cursor
declare #tbl_name varchar(1500)
--declare #sqlCommand varchar(1500)
declare cur cursor for select table_name from #DB_Tables
Open cur
--Loop through each table name from the first temp table
--then update the second temp table (#temp_table) with the record count
FETCH NEXT FROM cur into #tbl_name
While ##FETCH_STATUS = 0 BEGIN
declare #sqlCommand varchar(1500)
--query used to get the record count from the frist temp table (#DB_tables)
SET #sqlCommand = 'select count(*) from '+#tbl_name
UPDATE #temp_table
SET record_count = Execute(#sqlCommand)
END
CLOSE cur
Deallocate cur
select * from #temp_table
It's not easy to use table variables with execute because the dynamic SQL is executed in the different context and doesn't see the variable and you can't assign results from execute that way.
You can either insert the results into a table variable with this syntax:
insert into #temp_table
execute ('select ' + #tbl_name + ', count(*) from ' + #tbl_name ...)
Or use temp. tables, since then you can refer them also inside the dynamic SQL, so you could do something like:
create table #temp_table (
table_name varchar(1500),
record_count varchar(255),
drop_script varchar(1500),
update_script varchar(1500)
)
...
Execute('update #temp_table set record_count = (select count(*) from '
+#tbl_name+') where table_name = '''+#tbl_name+''')

Determine all columns from a table and write them separated by commas in a variable

--Dummy table
create table table1 (
column_order varchar (100)
)
insert into table1 values ('column1')
insert into table1 values ('column2')
insert into table1 values ('column3')
insert into table1 values ('column4')
insert into table1 values ('column5')
insert into table1 values ('column6')
--Start of select
declare #rowsCount INT
declare #i INT = 1
declare #column varchar(1000) = ''
set #rowsCount = (select COUNT(*) from table1)
while #i <= #rowsCount
begin
set #column = #column + (select column_order from table1 where rowid(table1) = #i) + ', '
set #i = #i + 1
end
select #column
This code has the function ROWID thats an IQ-Sybase funktion, and im not sure what other DBMS can use it. And above you have a example what i want my select to look like.
My problem is, you cant use the ROWID function with sys.column or any other systables. Has anyone an idea how to get the same select as mine without using the ROWID function.
If you are using IQ, i constructed the code so you can just type f5 and see the select statement, after that just drop the dummy table.
Use list(). It works in both the ASA system and IQ catalogs.
drop table if exists table1
go
create local temporary table table1 (
column_order varchar (100)
) in system --create table in system
insert into table1 values ('column1')
insert into table1 values ('column2')
insert into table1 values ('column3')
insert into table1 values ('column4')
insert into table1 values ('column5')
insert into table1 values ('column6')
declare #columns varchar(100)
select #columns = list(column_order) from table1
select #columns
go
I may be not understand your need, because I can't see why you need rowdid.
Usually, in TSQL, I do as follow:
declare #someVar as nvarchar(max)
set #someVar = (select
'[' + c.name + '],' as 'data()'
from
sys.columns c
join sys.tables t on c.object_id = t.object_id
where
t.name = 'SomeTableName'
for xml path(''))
print Left(#someVar, Len(#someVar) - 1)
Maybe you will need to use a cursor:
-- #MyTableID has to be definded somewhere or replace
DECLARE #columns varchar(32000)
DECLARE my_cursor CURSOR FOR
SELECT syscolumn.column_name FROM syscolumn WHERE syscolumn.table_id = #MyTableID
OPEN my_cursor
FETCH NEXT my_cursor into #column
WHILE ##FETCH_STATUS = 0
BEGIN
-- put your magic here
-- e.g.
-- SET #columns = #columns + column
FETCH NEXT my_cursor_pkey into #column
END
CLOSE my_cursor
DEALLOCATE my_cursor
Not tested yet, but something like that should work.

Execute Stored Procedure having a query as a parameter

How can I execute the sp_1 for every ProductId and get a result set?
EXEC sp_1 (SELECT ID FROM Products)
Try this way. No direct query it seems.
execute sp for each row
or try this , make small changes if needed.Use temp table to get values out of sp. Use the below inside a sp if needed.
begin
declare #ID int
declare #temp table (col1 int)
declare cur cursor for select distinct ID from products
open cur
fetch next from cur into #ID
truncate table #temp
while(##FETCH_STATUS=0)
begin
insert into #temp (<'cols/output from procedure'>) exec (#ID)
end
select * from #temp
end
I would store the id's in a temp table and use a WHILE loop (AVOID CURSORS!)
DECLARE #prodid INT
SELECT prodid, 0 as Processed INTO #prod_ids FROM Products
WHILE EXISTS (SELECT prodid FROM #prod_ids WHERE Processed = 0)
BEGIN
SELECT TOP 1 #prodid = prodid FROM #prod_ids WHERE Processed = 0
EXEC sp_1(#prodid)
UPDATE #prod_ids SET Processed = 1 WHERE prodid = #prodid
END
With dynamic query in SQL Server:
declare #cadena varchar(max) = ''
select #cadena = #cadena + 'exec sp_1 ' + ltrim(ID) + ';'
from Products;
exec(#cadena);