sp_generate_inserts for all the tables? or something similar - sql

I have two databases.
Database A - full of data
Database B - backup of database A, but without data
how can I get all data from database A and just merge it into database B?
My thoughts were to just generate an insert of the whole data or something.
Thanks

Take a look at redgate's SQL Data Compare.

OP said:
database is full of triggers and
constraints
Just restore a complete backup of A as a new database and be done with it. Lots of "one off" inserts created by a script will take forever, play havoc with your transaction log, and most likely fail because of FKs, etc.

That would work if you're trying to do something ongoing, but if you want to do it just once and you have SQL Server Management Studio installed, you can have it do the Export/Import for you. Here's a walk-though with some screenshots:
http://www.databasejournal.com/features/mssql/article.php/3580216/SQL-Server-2005-Import--Export-Wizard.htm

If you don't have any identity fields to worry about, and it's a one-time operation, you can do something like this, which uses sp_msforeachtable and dynamic SQL:
DECLARE #SQL varchar(max)
SET #SQL = '
INSERT INTO DatabaseB.? WITH (TABLOCK)
SELECT *
FROM DatabaseA.?'
exec sp_MSforeachtable #SQL

Related

SQL Server 17, database migration, function for setting identity in primary key

I have two twin databases and want to migrate one into another. For that I would like to have a written function so that primary key can be set by utils function. I did already by using UI in SQL Server, but that is tiresome, as there are many tables to repeat that process. Utils function would be setting identity before migrating table and then removing it after job is done.
For example:
insert into TABLE
(colum_names)
select column_names
from TABLE
Before and after I would like to set and remove identity automatically stead doing this:
I know there are ways around this with recreating tables, but for obvious reasons(query time, server load) I do not want to do that :)
If I'm not misunderstanding, you are using an external utility to perform this migration. In that case, you can execute the SET IDENTITY_INSERT [dbo].[YourTable] ON; statement in a command prior to your migration steps.
For example, with C#:
using(SqlConnection myConn= new SqlConnection(conn))
{
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "SET IDENTITY_INSERT [dbo].[YourTable] ON;";
//Migration steps here...
cmd.CommandText += "SET IDENTITY_INSERT [dbo].[YourTable] OFF;";
}
EDIT:
The below is actually incorrect! I overlooked that IDENTITY_INSERT can only be set for a SINGLE table per SESSION. See MS documentation
As per a the commented suggestion by #benjamin moskovits to use the undocumented sp_msforeachtable, while this would work to SET IDENTITY_INSERT for each table in your database, this approach is nevertheless a bit of a sledgehammer which may have unintended consequences depending on the specifics of your migration pattern.
exec sp_msforeachtable 'SET IDENTITY_INSERT ? ON;'
If you want to do something to each table in a database you can use the 'unsupported' but very widely used and available in almost every version of SQL Server, sp_msforeachtable to execute something....
exec sp_msforeachtable 'select count(*) ''?'' from ?'
will give you a list of every table in a database and the number of rows it contains.

Stored Procedure gives Cannot find object... error in SSIS, but works fine in SSMS

I am trying to build an SSIS package that dynamically rebuilds the indexes for all the tables in my database. The general idea is that the package will make sure that the table is not being update and then execute a stored procedure that drops the old index, if it exists, and then recreates it. The logic behind the package seems to be sound. The problem that I am having is when I execute the package I keep getting the error:
Cannot find object...because it does not exist or you do not have permission...
The index existing should be irrelevant due to the IF EXISTS part.
The procedure looks like this:
REFERENCE_NAME AS VARCHAR(50),
COLUMN_NAME AS VARCHAR(50),
INDEX_NAME AS VARCHAR(50)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #sql NVARCHAR(MAX)
SET #sql = 'IF EXISTS (SELECT name FROM sysindexes WHERE name = '+CHAR(39)+#INDEX_NAME+CHAR(39)+') '+
'DROP INDEX '+#INDEX_NAME+' ON '+#REFERENCE_NAME+' '+
'CREATE INDEX '+#INDEX_NAME+' ON '+#REFERENCE_NAME+'('+#COLUMN_NAME+') ON [INDEX]'
EXEC sp_executesql #sql
END
GO
I am able to execute the procedure through SSMS just fine, no error and it builds the index. When I execute the package in SSIS it errors out the minute it gets to the task that executes the stored procedure. I have made sure that SSIS is passing the variables to the execute SQL task and I have verified that I have db_ddladmin rights. Outside of that I am at a loss and have been beating my head against the wall for a day and a half on this.
Is there something I am missing, some permissions I need to request, or some work around for the issue?
Any information would be much appreciated.
Bartover, its definitely not looking at the wrong database. I have checked that the proc is there and the only connection on the package is to that specific database. Yes, I am executing the package manually with Visual Studios 2010 Shell Data Tools.
Sorrel, I tried your idea of a sanity check on the #sql statement on the drop, on both the drop and create, and on whole #sql statement, no joy.
Gnackenson, I had that same thought, but the connection authentication method is set to Windows Authentication, same as ssms. Do you have any ideas as to why it might use different permissions?
It looks like IF EXISTS is being ignored by SSIS SQL Task. To fix my problem, I altered my SQL tasks from DROP - CREATE to DISABLE - ENABLE.

SQL - How to insert results of Stored_Proc into a new table without specifying columns of new table?

Using SQL Server 2005, I'd like to run a stored procedure and insert all of the results into a new table.
I'd like the new table to have its columns automatically configured based upon the data returned by the stored procedure.
I am familiar with using the SELECT ... INTO syntax:
SELECT * INTO newtable FROM oldtable
Is this possible?
Edit for clarification: I'm hoping to accomplish something like:
Select * INTO newtable FROM exec My_SP
The only way to do this is w/ OPENROWSET against the local server:
SELECT * INTO #temp
FROM OPENROWSET (
'SQLOLEDB'
, 'Server=(local);TRUSTED_CONNECTION=YES;'
, 'SET FMTONLY OFF EXEC database.schema.procname'
) a
But this is kind of a last-ditch-gotta-do-it-damn-the-consequences kind of method. It requires elevated permissions, won't work for all procedures, and is generally inefficient.
More info and some alternatives here: http://www.sommarskog.se/share_data.html
This seems like a horrible design. You're really going to create a new table to store the results of a stored procedure, every time the stored procedure is called? And you really can't create the table in advance because you have absolutely no idea what kind of output the stored procedure has? What if the stored procedure returns multiple resultsets? What if it has side effects?
Okay, well, if that's what you really want to do...
One way to accomplish this is to use your local server as a linked server and utilize OPENQUERY. First you need to make sure your local server is configured for data access:
EXEC sp_serveroption 'local server name', 'DATA ACCESS', true;
Then you can do something like this:
SELECT * INTO dbo.newtable
FROM OPENQUERY('local server name', 'EXEC yourdb.dbo.yourproc;');
PS How are you going to write code that is going to perform SELECT INTO into a new table name every time (because you can only do SELECT INTO once)? Dynamic SQL? What happens if two users run this code at the same time? Does one of them win, and the other one just gets an error message?
A variation of the same is
create table somename
select * from wherever;

Simulate a table creation with SQL

Is there a standard way to simulate a table creation in a database by using SQL? I don't want the table to be created, just check if it could be created.
One way would be to create it and then delete it again.
Any other way?
Most major servers support transactional DDL, so you can do something along these lines:
begin transaction
create table Foo ...
rollback transaction
Theoretically, in case of error it should be reported back to client, but table will not be created altogether.
Depends on the SQL DBMS you're interested in. For example Postgres supports transactional DDL and the following will work:
START TRANSACTION;
CREATE TABLE ... ();
<check for error here>
ROLLBACK;
If you're using MySQL, you could create it using a transient storage engine, like MEMORY .
Really, you have to actually create it to make sure everything is OK.
Foreign key references, functions used as default or check constraints or in computed columns are not checked until execute time.
One basic method (SQL Server) is to use "SET FMTONLY ON".
Useful for checking the statement is valid, though won't tell you everything (e.g. if the table already exists).
This will succeed:
SET FMTONLY ON
EXECUTE ('CREATE TABLE SomeTable(SomeField INTEGER)')
SET FMTONLY OFF
This will not:
SET FMTONLY ON
EXECUTE ('CREATE TABLE SomeTable(dodgysyntax)')
SET FMTONLY OFF
This approach is probably more useful for SELECT statements, which is what I've used it for in the past. It doesn't actually execute the statement, but returns out the metadata.

Trigger to capture schema changes in the Server

Is it possible to implement something like the following trigger
CREATE TRIGGER [tr_AU_ddl_All_Server] ON DATABASE
WITH EXECUTE AS self
FOR DDL_DATABASE_LEVEL_EVENTS
AS
DECLARE
#data XML
, #rc INT
SET #data = EVENTDATA()
EXEC #rc = __AU.dbo.AU_DDLLog #data
GO
BUT on the whole server. My idea is to capture all schema changes across all the databases in the server.
As far as im concerned this is not possible in SQL Server 2005, but I'd like to know if anyone got something like this to work. I'd like to avoid having to implement a trigger in every single database.
Yes, SQL Server 2005 introducted the "DDL Triggers" - read an excellent article on it here at SQL Team.
This article shows nicely that they are two scopes for DDL triggers - server-wide, or database-wide. Those that are database-wide cannot be applied to the whole server - you'd have to set them up in each database.
Marc