Using "SELECT INTO" with Azure SQL to copy data from another DB - sql

I'm trying to automate the initialising of a SQL DB on Azure. For some (lookup) tables, data needs to be copied from a source DB into the new DB each time it is initialised.
To do this I execute a query containing
SELECT * INTO [target_db_name]..[my_table_name] FROM [source_db_name].dbo.[my_table_name]
At this point an exception is thrown telling me that
Reference to database and/or server name in 'source_db_name.dbo.my_table_name'
is not supported in this version of SQL Server.
Having looked into this, I've found that it's now possible to reference another Azure SQL DB provided it has been configured as an external data source. [here and here]
So, in my target DB I've executed the following statement:
CREATE MASTER KEY ENCRYPTION BY PASSWORD = '<password>';
CREATE DATABASE SCOPED CREDENTIAL cred
WITH IDENTITY = '<username>',
SECRET = '<password>';
CREATE EXTERNAL DATA SOURCE [source_db_name]
WITH
(
TYPE=RDBMS,
LOCATION='my_location.database.windows.net',
DATABASE_NAME='source_db_name',
CREDENTIAL= cred
);
CREATE EXTERNAL TABLE [dbo].[my_table_name](
[my_column_name] BIGINT NOT NULL
)
WITH
(
DATA_SOURCE = [source_db_name],
SCHEMA_NAME = 'dbo',
OBJECT_NAME = 'my_table_name'
)
But the SELECT INTO statement still yields the same exception.
Furthermore, a simple SELECT * FROM [source_db_name].[my_table_name] yields the exception "Invalid object name 'source_db_name.my_table_name'".
What am I missing?
UPDATE
I've found the problem: CREATE EXTERNAL TABLE creates what appears to be a table in the target DB. To query this, the source DB name should not be used. So where I was failing with:
SELECT * FROM [source_db_name].[my_table_name]
I see that I should really be querying
SELECT * FROM [my_table_name]

It looks like you might need to define that external table, according to what appears to be the correct syntax:
CREATE EXTERNAL TABLE [dbo].[source_table](
...
)
WITH
(
DATA_SOURCE = source_db_name
);
The three part name approach is unsupported, except through elastic database query.
Now, since you're creating an external table, the query can pretend the external table is an object native to our [target_db]- this allows you to write the query SELECT * FROM [my_table_name], as you figured out from your edits. From the documentation, it is important to note that "This allows for read-only querying of remote databases." So, this table object is not writable, but your question only mentioned reading from it to populate a new table.

As promised, here's how I handle database deploys for SQL Server. I use the same method for on-prem, Windows Azure SQL Database, or SQL on a VM in Azure. It took a lot of pain, trial and error.
It all starts with SQL Server Data Tools, SSDT
If you're not already using SSDT to manage your database as a project separate from your applications, you need to. Grab a copy here. If you are already running a version of Visual Studio on your machine, you can get a version of SSDT specific for that version of Visual Studio. If you aren't already running VS, then you can just grab SSDT and it will install the minimal Visual Studio components to get you going.
Setting up your first Database project is easy! Start a new Database project.
Then, right click on your database project and choose Import -> Database.
Now, you can point at your current development copy of your database and import it's schema into your project. This process will pull in all the tables, views, stored procedures, functions, etc from the source database. When you're finished you will see something like the following image.
There is a folder for each schema imported, as well as a security folder for defining the schemas in your database. Explore these folders and look through the files created.
You will find all the scripts created are the CREATE scripts. This is important to remember for managing the project. You can now save your new solution, and then check it into your current source control system. This is your initial commit.
Here's the new thought process to managing your database project. As you need to make schema changes, you will come into this project to make changes to these create statements to define the state you want the object to be. You are always creating CREATE statements, never ALTER statements in your schema. Check out the example below.
Updating a table
Let's say we've decided to start tracking changes on our dbo.ETLProcess table. We will need columns to track CreatedDateTime, CreatedByID, LastUpdatedDateTime, and LastUpdatedByID. Open the dbo.ETLProcess file in the dbo\Tables folder and you'll see the current version of the table looks like this:
CREATE TABLE [dbo].[ETLProcess] (
[ETLProcessID] INT IDENTITY (1, 1) NOT NULL
, [TenantID] INT NOT NULL
, [Name] NVARCHAR (255) NULL
, [Description] NVARCHAR (1000) NULL
, [Enabled] BIT DEFAULT ((1)) NOT NULL
, CONSTRAINT [PK_ETLProcess__ETLProcessID_TenantID]
PRIMARY KEY CLUSTERED ([ETLProcessID], [TenantID])
, CONSTRAINT [FK_ETLProcess_Tenant__TenantID]
FOREIGN KEY ([TenantID])
REFERENCES [dbo].[Tenant] ([TenantID])
);
To record the change we want to make, we simply add in the columns into the table like this:
CREATE TABLE [dbo].[ETLProcess] (
[ETLProcessID] INT IDENTITY (1, 1) NOT NULL
, [TenantID] INT NOT NULL
, [Name] NVARCHAR (255) NULL
, [Description] NVARCHAR (1000) NULL
, [Enabled] BIT DEFAULT ((1)) NOT NULL
, [CreatedDateTime] DATETIME DEFAULT(GETUTCDATE())
, [CreatedByID] INT
, [LastUpdatedDateTime] DATETIME DEFAULT(GETUTCDATE())
, [LastUpdatedByID] INT
, CONSTRAINT [PK_ETLProcess__ETLProcessID_TenantID]
PRIMARY KEY CLUSTERED ([ETLProcessID], [TenantID])
, CONSTRAINT [FK_ETLProcess_Tenant__TenantID]
FOREIGN KEY ([TenantID])
REFERENCES [dbo].[Tenant] ([TenantID])
);
I didn't add any foreign keys to the definition, but if you wanted to create them, you would add them below the Foreign Key to Tenant. Once you've made the changes to the file, save it.
The next thing you'll want to get in the habit of is checking your database to make sure it's valid. In the programming world, you'd run a test build to make sure it compiles. Here, we do something very similar. From the main menu hit Build -> Build Database1 (the name of our database project).
The output window will open and tell you if there are any problems with your project. This is where you'll see things like Foreign keys referencing tables that don't yet exist, bad syntax in your create object statements, etc. You'll want to clean these up before you check your update into source control. You'll have to fix them before you will be able to deploy your changes to your development environment.
Once your database project builds successfully and it's checked in to source control, you're ready for the next change in process.
Deploying Changes
Earlier I told you it was important to remember all your schema statements are CREATE statements. Here's why: SSDT gives you two ways to deploy your changes to a target instance. Both of them use these create statements to compare your project against the target. By comparing two create statements it can generate ALTER statements needed to get a target instance up to date with your project.
The two options for deploying these changes are a T-SQL change script, or dacpac. Based on the original post, it sounds like the change script will be most familiar.
Right click on your database project and choose Schema Compare.
By default, your database project will be the source on the left. Click Select target on the right, and select the database instance you want to "upgrade". Then click Compare in the upper left, and SSDT will compare the state of your project with the target database.
You will then get a list of all the objects in your target database that are not in the project (in the DROP section), a list of all objects that are different between the project and target database (in the ALTER Section), and a list of objects that are in your project and not yet in your target database (in the ADD section).
Sometimes you'll see changes listed that you don't want to make (changes in the Casing of your object names, or the number of parenthesis around your default statements. You can deselect changes like that. Other times you will not be ready to deploy those changes in the target deployment, you can also deselect those. All items left checked will either be changed in target database, if you choose update (red box below), or added to your change script (green box below), if you hit the "Generate Script" icon.
Handling lookup data in your Database Project
Now we're finally to your original question, how do I deploy lookup data to a target database. In your database project you can right click on the project in Solution Explorer and choose Add -> New Item. You'll get a dialog box. On the left, click on User Scripts, then on the right, choose Post-Deployment Script.
By adding a script of this type, SSDT knows you want to run this step after any schema changes. This is where you will enter your lookup values, as a result they're included in source control!
Now here's a very important note about these post deployment scripts. You need to be sure any T-SQL you add here will work if you call the script in a new database, in an existing database, or if you called it 100 times in a row. As a result of this requirement, I've taken to including all my lookup values in merge statements. That way I can handle inserts, updates, and deletes.
Before committing this file to source control, test it in all three scenarios above to be sure it won't fail.
Wrapping it all up
Moving from making changes directly in your target environments to using SSDT and source controlling your changes is a big step in the maturation of your software development life-cycle. The good news is it makes you think about your database as part of the deployment process in a way that is compatible with continuous integration/continuous deployment methods.
Once you get used to the new process, you can then learn how to add a dacpac generated from SSDT into your deployment scripts and have the changes pushed at just the right time in your deployment.
It also frees you from your SELECT INTO problem, your original problem.

Related

Create table or only add changed/new columns

I have several tables which are worked on within a development environment, then moved to production. If they don't already exist in production, it's fine to just generate the table creation script from SSMS and run it. However, there are occasions where the table already exists in production but all that's needed is an extra column or constraint. The problem is knowing exactly what has changed.
Is there a way to get SQL to compare my CREATE TABLE statement against the existing table and only apply what has changed? Essentially I am trying to do the below and SQL correctly complains that the table exists already.
I would have to manually write an ALTER query which on a real example would be difficult due to the sheer volume of columns. Is there a better / easier way to see what has changed? Note that this involves two separate database servers.
CREATE TABLE suppliers
( supplier_id int NOT NULL,
supplier_name char(50) NOT NULL,
contact_name char(50),
CONSTRAINT suppliers_pk PRIMARY KEY (supplier_id)
);
CREATE TABLE suppliers
( supplier_id int NOT NULL,
supplier_name char(50) NOT NULL,
contact_name char(50),
contact_number char(20), --this has been added
CONSTRAINT suppliers_pk PRIMARY KEY (supplier_id)
);
Also, dropping and recreating wouldn't be a possibility because data would be lost.
SSMS can generate the schema change script if you make the change in the table designer (right-click on the table in Object Explorer and select Design). Then, instead of applying the change immediately, from the menu select Table Designer-->Generate Change Script. Note that depending on the change, SSMS may need to recreate the table, although data will be retained. SSMS requires you uncheck the option to "prevent saving changes that require table re-creation" under Tools-->Options-->Designers-->Table and Database Designers. Review the script to make sure you're good with it.
SQL Server Data Tools (SSDT) and third-party tools (e.g. from Red-Gate and ApexSQL) have schema-compare features to generate the needed DDL after the fact. There are also features like migration scripts to facilitate continuous integration and source control integration as well. I suggest you keep database objects under source control and leverage database tooling as part of your development process.
Typically we use something like database migrations for this, as a feature outside of the database. For example, in several of our C# apps we have a tool called FluentMigrator. We write a script that adds the new columns we need in code, to the dev database. When the project is debugged, FM will run the script and modify the dev db, the dev code uses the new columns and all is well. FM knows not to run the script again
When time comes to put something live, the FM script is a part of the release, the app is put live onto the website, the migrations run again updating the live db so the live code will use the new columns and still all is well..
If there is nothing outside of your sql server (not sure how you manage that, but..), then surely you must be writing scripts (or using gui to generate scripts) that alter the DB right? So just keep those scripts and run them as part of the process of "going live"
If you are looking at this from a perspective that these db already exist created by someone else and they threw away the scripts, then you can one time catch up using a Database Schema Compare tool. Microsoft have one in SSDT - see here for more info on how it is used:
https://msdn.microsoft.com/en-us/library/hh272690(v=vs.103).aspx
If you don't have many constraints I suggest you create a dynamic script to cast and import the data into your new tables. If this doesn't fail then you just drop the old tables and rename the newly created ones.

Remove All Permission In SSRS 2008

Must remove all the permissions SSRS 2008 all reports and leave only one group, is there any way via script in PS, VB, T-SQL that performs this task?
I can see 2 ways of doing it:
The recommended (supported) way
Go through all reports and restore the parent security.
This can take a lot of time depending on the number or reports you have.
The unsupported way
This should do what you want without too much work, but is quite risky.
Backup your ReportServer DB (important)
Apply the permissions you want on the root in the web interface
Go in the Catalog table and look for the PolicyID of the corresponding entry (it should be the first line, with almost all other columns = NULL, and PolicyRoot = 1)
Execute the following query:
update [dbo].[Catalog] set [PolicyID] = <YourRootPolicyID>
(Optional) Clean the PolicyUserRole table, which maps a user to a role and a policy:
delete from [dbo].[PolicyUserRole] where [PolicyID] <> <YourRootPolicyID>
(Optional) Clean the Policies table, which holds the list of policies (= security settings):
delete from [dbo].[Policies] where [PolicyID] <> <YourRootPolicyID>
All your items will now have same the security settings.

How to move Database Diagram from One Server to Another Server

I have created a new Database Diagram in Test Database and it is in sitde01 Server. Now I want to move it to another server. How do I migrate it to another server.
It can be done, but it's a royal pain. Here's an outline of the process and some scripts.
Diagrams are stored in a "system" table named sysDiagrams. This table (only?) gets created when you click on the diagrams node in SSMS, it asks you if you want to create the objects that support diagrams, and you click "Yes". Do so on both your source and target databases.
Create the diagram or diagrams in the "source" database.
Review the structure and contents of sysDiagrams. Note that column diagram_id is an identity column. 1 row gets stored for every diagram. (You don't care, but it used to be 4 or 5 rows in SQL 2000.)
To copy to another database on the same SQL instance, the simplest way is to do INSERT... SELECT... between tables. With that identity column in the way, you'll have to fuss with SET IDENTITY_INSERT, and perhaps assign a new identity value on the target computer. Irritating, but not critically hard.
The following script will copy all diagrams from one database to another that's on the same server (this is how I archive complex diagrams that took waaaay too long to create, from databases that are prone to get dropped and recreated):
USE TargetDatabase
DELETE sysDiagrams
where name in (select name from SourceDatabase.dbo.sysDiagrams)
SET identity_insert sysDiagrams on
INSERT sysDiagrams (name, principal_id, diagram_id, version, definition)
select name, principal_id, diagram_id, version, definition
from SourceDatabase.dbo.sysDiagrams
SET identity_insert sysDiagrams off
To copy to another database on a different SQL instance (or server), well, it gets even harder. I use temporarily created Linked Server definitions, using scripts I sweated bullets over years ago and never want to have to modify again (i.e. post a different question so someone who knows can tell you how they work), and modify the scripts with appropriate four-part naming conventions. Other options (OPENROWSET and the like) are possible, but I'm even less familiar with those.
If you want to move your diagrams from one instance or server to a different one, and you don't want to restore the whole database, you can do the following.
If it doesn't exist, create the database on your target server. You also have to click on the "Database Diagrams" node in SSMS to have it create a dbo.sysDiagrams table.
Then make sure to import all the schema information you need in your diagram. Because your diagram will point to these. I.e. tables, PK, FK etc. must be present.
Backup your database on the source server.
Restore it into a temporary database on the target server. In this way you get all your diagram information into the target server.
Copy the information from the dbo.sysDiagrams table in the temporary database into the dbo.sysDiagram table of your target database. You could do something like this (adapted the code from Philip Kelley):
USE TargetDatabase
SET identity_insert sysDiagrams on
INSERT sysDiagrams (name, principal_id, diagram_id, version, definition)
select name, principal_id, diagram_id, version, definition
from TempDatabase.dbo.sysDiagrams
SET identity_insert sysDiagrams off
This solution worked excelent for me. Of course if you don't want all the diagrams or if other diagrams are existing in the target database, you have to filter the select statement and do some identity_insert manipulation, but this shouldn't be too difficult.
In order to move the database-diagram you will need to migrate all the tables and triggers included in that diagram. The easiest way to do this is backup the db and restore on the other server.

Cannot modify table ( using microsoft sql server management studio 2008 )

I create 2 tables and another 1 with foreign keys to the other two.
I realized I want to make some changes to table no 3.
I try to update a field but I get an error "Saving changes is not permitted. The changes you have made require the following table to be dropped and re-created."
I delete those 2 relationships but when I look at dependencies I see my table still depends on those 2 and I still cannot make any change to it.
What can I do?
You can also enable saving changes that require dropping of tables by going to "tools->options->designers->Table and database designers" and unchecking "Prevent saving changes that require table re-creation"
Be careful with this though, sometimes it'll drop a table without being able to recreate it, which makes you lose all data that was in the table.
When using Microsoft SQL Server Management Studio 2012, the same message occurs.
I used the script feature to do modifications which can be seen as a rather good workaround if you wanna use the designer only within a "safe" mode.
Especially the GUI related to create a foreign key is not the best in my opinion. When using a script (alter table) for adding a fk, you are faster than using this GUI feature.
When adding/writing a 'not' in prior to null, that's not a hard issue. (Removing an 'Allow Nulls' for a column refers to "Saving changes is not permitted" when using the designer.)

sql server helper stored procedure or utility for alter table alter column IDENTITY(1,1)

I wanted to modify a column in a sql server 2005 table to IDENTITY(1,1)
Incidentally this table is empty and the column to be changed is a primary key.
This column is also a foreign key for two other tables.
After googling I found that you cannot use Alter table syntax to modify a column and make it an indentity column.
Link #1 : How do I add the identity property to an existing column in SQL Server
Link #2 : Adding an identity to an existing column -SQL Server
I ended up checking the dependent tables (2 of them) removing the foreign keys (generated the script from SSMS) then dropping the main table then re-creating with identity. (could try the rename option here as well)
Then re-created the foreign keys for the earlier dependent two tables.
But all this was manual work, any scripts or SPs out there to make this easier.
Ideally all these steps would be done by such a script/tool/utility:
Check dependent tables keys
Generate Create and drop foreign key scripts for this
Generate create script for the main table
drop the main table (or rename the table if the table has data)
re-create the table with identity column enabled
re-create foreign keys
You can use SSMS to generate a script (Edit a table, save script), but otherwise it's a manual process as you identified.
The SSMS scripts will pick up dependencies etc. For this kind of work, I tend to use SSMS to generate a basic script, pimp it a bit, run it carefully, then use a comparison tool (such as Red Gate compare) to generate a safer version.
Edit: The SSMS error is not an error, it's a safety check that can be switched off
(This is merely a follow-up to gbn's post with more details -- it isn't all that easy to figure this stuff out.)(
It isn't impossible to write a utility to do this, just very complex and very hard. Fortunately, Microsoft has already done it -- its called SSMS (or SMO?). To generate such a script:
In the Object Explorer, drill down to the database and table that you want to modify
Right click and select Design
Make the desired changes to the one table in the design screen. It's reasonably intuitive.
To add/remove the identity property, select the column in the upper pane, and in the lower pane/"Column Properties" tab, expand and configure the settings under "Identity Specification".
To generate a script to implement all your changes, incorporating all the dependent key changes, click on the "Generate Change Script" toolbar button. This is also an option under the "Table Designer" menu.
I also do this to generate scripts (that I later modify--SSMS doesn't always produce the most efficient code.) Once done, you can exit out without saving your changes -- leaving you a DB you can test your new script on.
drop the pk and build the same datatype column
copy the data of the column which you want to set identity to the new column.
drop the old column
reset primary key
ALTER TABLE UserRole
DROP CONSTRAINT PK_XX
ALTER TABLE XX
ADD newX int not null identity(1,1) primary key
update XX set newX = oldX
alter table XX
DROP COLUMN oldX
this is the simplest way to set identity column.
if you don't want to use the long generated script.