SQL Server: is it possible to script table as UPDATE? - sql

I need to export/script two tables to my local database to a remote anyway.
Anyway I cannot export them as INSERT INTO scripts because I cannot drop them in the remote database and populate them again (because of FK and integrity constraints). So, is it possibile to script tables as UPDATE statements for each row, instead of INSERT INTO? I'm using SQL Server 2008/2012

CREATE TABLE mytable(
ExtractTypeNum INTEGER NOT NULL --PRIMARY KEY
,FileOrderNum VARCHAR(11)
,PrevFileOrderNum VARCHAR(11)
,NextFileOrderNum VARCHAR(11)
,rownum1 INTEGER
,Statusflag1 VARCHAR(9)
);
INSERT INTO mytable(ExtractTypeNum,FileOrderNum,PrevFileOrderNum,NextFileOrderNum,rownum1,Statusflag1)
VALUES (1,'2016-09-191',NULL,'2016-09-192',1,'IsInitial');
INSERT INTO mytable(ExtractTypeNum,FileOrderNum,PrevFileOrderNum,NextFileOrderNum,rownum1,Statusflag1)
VALUES (2,'2016-09-192','2016-09-191','2016-09-201',2,NULL);
INSERT INTO mytable(ExtractTypeNum,FileOrderNum,PrevFileOrderNum,NextFileOrderNum,rownum1,Statusflag1)
VALUES (3,'2016-09-201','2016-09-192','2016-09-211',3,NULL);
select 'Update Table Xyz Set Abc='+Convert(varchar(25),rownum1)+' ' as X,*
from myTable

There is many ways to sync data between databases. As my experience, you can do by 2 main ways:
Using MERGE statement (it supports from mssql 2k8: https://msdn.microsoft.com/en-us/library/bb510625.aspx)
write dynamic query to generate data script for 2 target tables:
Select 'select * into #tmp from dbtarget.tbla where 1<0;' as data
Union
Select 'insert into #tmp values(' + convert(varchar, cola) + ', ' + convert(varchar, colb) + ', ' + convert(varchar, colc) + ');' as data from dbsource.tbla;
run the query above at database source to get output script data.
apply script data to target database.
using MERGE statement to merge data between #tmp table and target table.
Utilize Log Shipping feature to sync data between databases in the same structure and in one domain network.
https://msdn.microsoft.com/en-us/library/ms190640(v=sql.110).aspx

Many thanks to Alfaiz Ahmed this is my final working script:
select 'UPDATE ERGO.DBO.RESIDENZE SET CODISEDERESI='+CONVERT(varchar(50),CODISEDERESI)+
',DESCRIRESIDE='+isnull(CONVERT(varchar(100),''''+replace(DESCRIRESIDE,'''','''''')+''''),'''''')+
',INDIRIRESIDE='+isnull(CONVERT(varchar(100),''''+replace(INDIRIRESIDE,'''','''''')+''''),'''''')+
',NOMERESIDENZ='+isnull(CONVERT(varchar(50),''''+replace(NOMERESIDENZ,'''','''''')+''''),'''''')+
',VIARESIDENZA='+isnull(CONVERT(varchar(50),''''+replace(VIARESIDENZA,'''','''''')+''''),'''''')+
',CAPRESIDENZA='+isnull(CONVERT(varchar(50),''''+CAPRESIDENZA+''''),'''''')+
',CITTARESIDEN='+isnull(CONVERT(varchar(50),''''+replace(CITTARESIDEN,'''','''''')+''''),'''''')+
',EMAILRESIDEN='+isnull(CONVERT(varchar(100),''''+EMAILRESIDEN+''''),'''''')+
' WHERE CODICERESIDE='+CONVERT(varchar(50),CODICERESIDE)
from RESIDENZE
I had to use that replace() function because many Italian names have a single quote in their names so, for example, I wanted string D'AZEGLIO to become D''AZEGLIO in order to be correctly processed by SQL. Finally, before execute the query I press CTRL+SHIFT+F to save the output to a sql file as a generated script.

Related

Using dynamic Server and Database Name in SQL Server stored procedure over linked servers

I have a requirement.
Using SSIS i am import data from flat file/excel file into my staging table. From staging table i need to filter data and transfer it to different databases over different linked server.i.e. let say for California i have dbCalifornia on Server A, For Taxes i have dbTaxes on Server B etc etc.
I need to read config table and redirect data accordingly.i.e. if column value =CALI insert data in dbCalifornia.tblA, for column value =TAX insert data in dbTaxes.tblA. I am trying to use Server Name and Database name as variable (because i am reading these from config table) i.e.
INSERT INTO [#server].[#database].[DBO].[BASIC]
But i am getting error .
I am not expert DBA please suggest my solution how can i implement this scenario.
TIA
You can do it using dynamic sql like this:
declare #server varchar(100), #database varchar(100);
DECLARE #sql varchar(8000) ='INSERT INTO[' + #server +'].['+ #database + '.[DBO].[BASIC]' +
'(EmpID,EmployeeID,ADDR1, ADDR2, ADDR3,ADDR4,TELNUM,MARRIED,LNAME,MNAME,FNAME,' +
'SEX, EMAIL,COUNTRYCODE, CITIZEN) ' +
'select EmpID,EmployeeID,ADDR1, ADDR2, ADDR3,ADDR4,TELNUM,MARRIED,LNAME,MNAME,FNAME,
SEX, EMAIL,COUNTRYCODE, CITIZEN from dbo.myExcelTable where state = ' + #database;
exec(#sql);
I don't understand what are your 100 variables tht you use in your insert,
didn't you say
if column value =CALI insert data in dbCalifornia.tblA, for column
value =TAX insert data in dbTaxes.tblA.
?
So you just need to filter your table using #database value and insert those rows in corresponding table
normally when reading a table from another server and DB. I use the LinkedServer, user and table like this:
Select * from Link..User.Table ;
after a linked server I have to use 2 dots.
I don't know if this can help since this is to read from an Oracle database.

Querying the same table for a list of databases in MS SQL Server

This is my first time posting on SO, so please go easy!
I'm attempting to write a SQL script that queries the same table for a list of databases in a single SQL Server instance.
I have successfully queried the list of databases that I required using the following, and inserting this data into a temp table.
Select name Into #Versions
From sys.databases
Where name Like 'Master%'
Master is suffixed with numerical values to identify different environments.
Select * From #Versions
Drop Table #Versions
The table name I am trying to query, is the same in each of the databases, and I want to extract the newest value from this table and insert it into the temp table for each of the database names returned.
I have tried researching this but to no avail. I am fairly comfy with SQL but I fear I could be out of my depth here.
You can do the following. Once you have the list of your databases, you can build up the query (you need to edit it for your purpose).
Select name Into #Versions
From sys.databases
Where name Like 'test%'
declare #sql as varchar(max) = ''
select #sql = #sql + 'INSERT INTO sometable SELECT TOP 1 * FROM ' + name + '..sourcetable ORDER BY somedate DESC; '
FROM #Versions
exec (#sql)
Drop Table #Versions
Look at The undocumented sp_MSforeachdb procedure and here

SQL Server - Create a copy of a database table and place it in the same database?

I have a table ABC in a database DB. I want to create copies of ABC with names ABC_1, ABC_2, ABC_3 in the same DB. How can I do that using either Management Studio (preferably) or SQL queries ?
This is for SQL Server 2008 R2.
Use SELECT ... INTO:
SELECT *
INTO ABC_1
FROM ABC;
This will create a new table ABC_1 that has the same column structure as ABC and contains the same data. Constraints (e.g. keys, default values), however, are -not- copied.
You can run this query multiple times with a different table name each time.
If you don't need to copy the data, only to create a new empty table with the same column structure, add a WHERE clause with a falsy expression:
SELECT *
INTO ABC_1
FROM ABC
WHERE 1 <> 1;
Copy Schema (Generate DDL) through SSMS UI
In SSMS expand your database in Object Explorer, go to Tables, right click on the table you're interested in and select Script Table As, Create To, New Query Editor Window.
Do a find and replace (CTRL + H) to change the table name (i.e. put ABC in the Find What field and ABC_1 in the Replace With then click OK).
Copy Schema through T-SQL
The other answers showing how to do this by SQL also work well, but the difference with this method is you'll also get any indexes, constraints and triggers.
Copy Data
If you want to include data, after creating this table run the below script to copy all data from ABC (keeping the same ID values if you have an identity field):
set identity_insert ABC_1 on
insert into ABC_1 (column1, column2) select column1, column2 from ABC
set identity_insert ABC_1 off
If you want to duplicate the table with all its constraints & keys follows this below steps:
Open the database in SQL Management Studio.
Right-click on the table that you want to duplicate.
Select Script Table as -> Create to -> New Query Editor Window.
This will generate a script to recreate the table in a new query window.
Change the table name and relative keys & constraints in the script.
Execute the script.
Then for copying the data run this below script:
SET IDENTITY_INSERT DuplicateTable ON
INSERT Into DuplicateTable ([Column1], [Column2], [Column3], [Column4],... )
SELECT [Column1], [Column2], [Column3], [Column4],... FROM MainTable
SET IDENTITY_INSERT DuplicateTable OFF
1st option
select *
into ABC_1
from ABC;
2nd option: use SSIS, that is right click on database in object explorer > all tasks > export data
source and target: your DB
source table: ABC
target table: ABC_1 (table will be created)
This is another option:
select top 0 * into <new_table> from <original_table>
You need to write SSIS to copy the table and its data, constraints and triggers. We have in our organization a software called Kal Admin by kalrom Systems that has a free version for downloading (I think that the copy tables feature is optional)
In Case you want to do it N times (may be not practical in real world), you might try this:
declare #counter int
set #counter = 2
declare #tname NVARCHAR(100)
DECLARE #SQString NVARCHAR(MAX)
while(#counter <= 20) -- duplicate 20 times
begin
SET #tname= concat('Table_',#counter)
SET #SQString = 'select * into ' + #tname + ' from Table_1'
EXEC (#SQString)
set #counter = #counter + 1
End
use sql server manegement studio or netcat and that will be easier to manipulate sql

Insert results of execute(#QueryString) into a table while adding an extra column

I am writing a stored procedure that dynamically creates a SQL string, #SQLQuery. After I create this query, I need to execute the query and insert it into a table in the database while adding another column that specifies a unique ID for this particular insert. (Context: It is possible in this application that multiple groupings of data will be inserted into this table and I need to be able to differientiate between groupings at a later date. )
This issue is similar to this question except I am using Microsoft SQL Server 2008 instead of mysql. I have tried the solution there:
INSERT INTO data_table_name
EXECUTE(#SQLQuery), #SomeID
but MS SQL Server 2008 doesn't like that syntax.
Any ideas on how to do this in SQL Server 2008?
You can store query result in table variable and then read from that with extra column and write to final table
DECLARE #temp table (col1 int, col2 varchar(10), ....)
INSERT INTO #temp
EXEC(#SQLQuery)
INSERT INTO data_table_name
SELECT *, #SomeID FROM #temp
You can also append #SomeID in your dynamic sql string.
Example:
SET #SQLQuery = 'SELECT *,' + #SomeID + ' FROM ' + #tableNameVar
and then do this
INSERT INTO data_table_name
EXECUTE(#SQLQuery)
Since you mentioned you are doing this in a Stored Procedure, what I would suggest is for you to:
Execute the #SQLQuery first;
Upon successful execution of the #SQLQuery, insert the #SQLQuery to the table with the unique ID.
i.e.
EXEC sp_executesql #SQLQuery, #Param
IF ##ERROR <> 0
BEGIN
INSERT INTO TableA(Query)
VALUES(#SQLQuery)
END
You're better off designing TableA such that the ID will be an Identity so that a unique sequential ID is generated when you insert a record into that table.

automatically placing results of a called procedure into a select statement

I'm playing with some code from an article written by Peter Brawley found here on page 6 of the pdf. I'm trying to figure out how to automate it so that the result of the procedure is automatically placed in the select query. Right now what I am doing is calling the procedure, exporting the result into a text file, going to the text file manually (point click with mouse), copying the result and pasting it into a select statement. I haven't been able to figure out how to either insert the select statement into the procedure, or put the procedure into a table in my database or variable that I can call from the select statement. Any ideas?
Here is the sample code from Peter Brawley, that I've been trying to automate:
use database;
DROP PROCEDURE IF EXISTS writesumpivot;
DELIMITER |
CREATE PROCEDURE writesumpivot(
db CHAR(64), tbl CHAR(64), pivotcol CHAR(64), sumcol CHAR(64)
)
BEGIN
DECLARE datadelim CHAR(1) DEFAULT '"';
DECLARE comma CHAR(1) DEFAULT ',';
DECLARE singlequote CHAR(1) DEFAULT CHAR(39);
SET #sqlmode = (SELECT ##sql_mode);
SET ##sql_mode='';
SET #pivotstr = CONCAT( 'SELECT DISTINCT CONCAT(', singlequote,
',SUM(IF(', pivotcol, ' = ', datadelim, singlequote,
comma, pivotcol, comma, singlequote, datadelim,
comma, sumcol, ',0)) AS `',
singlequote, comma, pivotcol, comma, singlequote, '`',
singlequote, ') AS sumpivotarg FROM ', db, '.', tbl,
' WHERE ', pivotcol, ' IS NOT NULL' );
-- UNCOMMENT TO SEE THET MIDLEVEL SQL:
-- SELECT #pivotstr;
PREPARE stmt FROM #pivotstr;
EXECUTE stmt;
drop prepare stmt;
SET ##sql_mode=#sqlmode;
END
|
DELIMITER ;
call writesumpivot('database', 'table', 'pivotcol','sumcol');
Then the Select statement is as follows:
SELECT
infoField
[results of the call]
FROM
database.table
GROUP BY infoField;
Assuming I've ran the call, exported the results, copied them and pasted them into the select statement, my personal results of the call in the SELECT query would look something like this:
SELECT
infoField
,SUM(IF(pivotcol = "Yellow",sumcol,0)) AS `Yellow`
,SUM(IF(pivotcol = "Red",sumcol,0)) AS `Red`
,SUM(IF(pivotcol = "Purple",sumcol,0)) AS `Purple`
,SUM(IF(pivotcol = "Orange",sumcol,0)) AS `Orange`
,SUM(IF(pivotcol = "Green",sumcol,0)) AS `Green`
,SUM(IF(pivotcol = "Blue",sumcol,0)) AS `Blue`
,SUM(IF(pivotcol = "White",sumcol,0)) AS `White`
FROM database.table
GROUP BY infoField;
Running the above select statement gives me the pivot table that I need. I'm tryig to figure out how to incorporate this into a website, which is why it needs to be automated.
I tried inserting a create table, and then reference the table, but didn't get desired results.
Edited the last section of the PROCEDURE as follows:
--SELECT #pivotstr;
DROP TABLE IF EXISTS temp2;
CREATE TABLE IF NOT EXISTS temp2(sumpivotarg varchar(8000));
PREPARE stmt FROM #pivotstr;
...
changed call and select as follows:
call writesumpivot('database','table','pivotcol','sumcol');
insert into temp2(sumpivotarg) values(#pivotstr);
SELECT
table.infoField, temp2.sumpivotarg
FROM table, temp2
GROUP BY infoField
Results from this were the generic code rather than summing the contents of the cells in the database. it looks something like this:
infoField | sumpivotarg <-- Col Headings
123 | SELECT DISTINCT CONCAT('Sum(if(pivotcol=",pivotcol",sumcol,0)) AS'pivotcol,'')..
124 | SELECT DISTINCT CONCAT('Sum(if(pivotcol=",pivotcol",sumcol,0)) AS'pivotcol,'')..
125 | select DISTINCT CONCAT('Sum(if(pivotcol=",pivotcol",sumcol,0)) AS'pivotcol,'')..
I do not mean any disrespect towards mySQL, but this whole writing to a temp table solution for passing tablular data between stored procedures is suboptimal and dangerous (in real world transaction processing). I truly hope that the mySQL team will build in some enterprise level stored procedure functionality. Also, mySQL Functions not being able to return tables is a distinct disadvantage.
I have been slowly moving process over to Linux and mySQL from MSSQL. The short comings of mySQL in the procedure and function department is forcing some major kludgey type rewrites (ala temp tables and globals, etc).
I have been writing SPs for about 20 years (Sybase before SQL Server) and feel strongly that using dynamic SQL does not take advantage of the server side database. Many folks try to implement a Data layer at the client level, but the sever is better suited to this task. It is a natural division of functionality and data. Also, simultaneously running multiple precompiled calls at the server is quite a bit more optimal than repeated calls to the server, for the same processes.
Come on mySQL team, I am keeping my fingers crossed....
You could create a temp table in your DB. Use SQL insert to insert data into temp table as the result of the stored procedure execution. Afterwards you could use that temp table inside your select statement.
Here's an answer that shows how to do that:
Use result set of mysql stored procedure in another stored procedure
Just to mention a similar question:
MySQL How to INSERT INTO temp table FROM Stored Procedure