Update the timestamp columns of a SQL Server Filetable programatically? - sql-server

I have a filetable in a SQL Server database, with both T-SQL and Windows Share I/O access enabled.
I have a C# WinForms front end that loads files from this filetable, modifies and updates them back into the filetable. This is all working fine, and I can verify the file contents are getting updated correctly by both the changing file_stream binary as viewed directly in SSMS, and by viewing the files through the Windows Filetable share.
However, the creation_time, last_write_time and last_access_time columns of the filetable are not updated automatically when updating the files using T-SQL.
I've dug through the MSDN pages, which state the columns are 'calculated automatically', but this appears not to be the case.
Updating the files by simply opening them from the share, editing and saving them, does cause the columns to automatically update.
My stored procedure for updating the file_stream binary column is:
ALTER PROCEDURE [dbo].[updateFileBinary]
#fileId uniqueidentifier,
#fileBinary VARBINARY(MAX)
AS
BEGIN
SET NOCOUNT ON;
UPDATE files
SET file_stream = #fileBinary
WHERE stream_id = #fileId;
END
I have seen here that "Describes how Transact-SQL data manipulation language (DML) commands work with FileTables........ Updates can be made to the FILESTREAM data in the file_stream column without affecting any of the other columns, including the timestamps."
That says can be made, but how do we do a T-SQL update and do update those columns?

Related

SQL Server drop table and delete data form file system

I wans to completely remove any data from the file system after a drop table.
Is there any way to do that?
If you are referring to FILESTREAM Data, you can execute
EXEC SP_FILESTREAM_FORCE_GARBAGE_COLLECTION
Actually you need to execute twice.
More info here:
https://learn.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/filestream-and-filetable-sp-filestream-force-garbage-collection?view=sql-server-ver16

How can I create backup script from diagram in SQL Server?

I use SQL Server 2012 and SQL Server 2008 R2.
I create a script from all object (tables / trigger / stored procedure / function ...) in my database.
I generated this script from SQL Server Management Studio. I can recreate my database with this scrips on the other server. But I miss all diagrams of my database after run my script for create another database.
Therefore, I need create backup script from all diagrams that exist in my database.
I need execute this script on the destination database for recreating all my diagrams.
I found this Link. but i need some thinks that create all script (Insert Command) automatically.
I have found a reasonable solution. The problem is that Management Studio cannot display more that 65535 characters for Non-XML data, and cannot be set to display more than 65535.
See code for documentation :)
Backup script:
-- 1. Read from DB, using XML to workaround the 65535 character limit
declare #definition varbinary(max)
select #definition = definition from dbo.sysdiagrams where name = 'ReportingDBDiagram'
select
'0x' + cast('' as xml).value('xs:hexBinary(sql:variable("#definition") )', 'varchar(max)')
for xml path('')
-- 2. Open the result XML in Management Studio
-- 3. Copy the result
-- 4. Paste this in backup script for #definition variable
Restore script:
declare #definition varbinary(max)
set #definition = 0xD0CF -- Paste 0x0 value from Backup script
-- Create diagram using 'official' Stored Procedure
exec dbo.sp_creatediagram
#diagramname = 'ReportingDBDiagramCopy',
#owner_id = null,
#version = 1,
#definition = #definition
Scripting your database does not include diagrams as they are not server objects in the same way as a table or stored procedure; they exist as data in the sysdiagrams table.
A similar question on SO asked How do you migrate SQL Server Database Diagrams to another Database?
The accepted answer is to copy the contents of the sysdiagrams table to the new database, so you could include the table contents in your script. The answer with the most up-votes has a link to a way of scripting diagrams.
I've tried backing up and then restoring a database to the same server, deleting the diagram I had created (I only had one) and then running the following query:
INSERT INTO database2.dbo.sysdiagrams
(
NAME
,principal_id
,version
,DEFINITION
)
SELECT NAME
,principal_id
,version
,DEFINITION
FROM database1.dbo.sysdiagrams
The diagram was successfully restored, however I did do this on a restored backup, I should really test it with a new database generated from a script.
UPDATE:
I scripted a database and then created a new database from it. When trying to rebuild the diagrams using an INSERT statement I got the error
So although it seems possible it's not trivial to create diagrams in a new database created from a script. Go with the answer given regarding scripting diagrams and modify it for your own needs.
Perhaps you can investigate further and post your own answer :)
Here's a quick & dirty method I use. Since the query window won't display the full varbinary(max) value of the definition field, but the XML editor will, I output the rows to XML as follows:
Run the following query on the server/database that contains the diagrams:
SELECT 'INSERT sysdiagrams(name,principal_id,diagram_id,version,definition) VALUES('''+name+''','
+CONVERT(varchar(2),principal_id)+','+CONVERT(varchar(2),diagram_id)+','+CONVERT(varchar(2),version)+','
+'0x' + CAST('' as xml).value('xs:hexBinary(sql:column("definition"))','varchar(max)') +')'
FROM RCSQL_ClaimStatus.dbo.sysdiagrams
FOR XML PATH
Click on the generated link to open the XML result, and ctrl-a & ctrl-c to copy all rows generated.
Paste that output back into your query window. I usually paste it between a pair of IDENTITY_INSERT's like this:
--TRUNCATE TABLE sysdiagrams
SET IDENTITY_INSERT sysdiagrams ON;
<row>INSERT sysdiagrams(name,principal_id,diagram_id,version,definition) VALUES('ERD1',1,1,1,0xD0CF11E0A1B11AE100000...)</row>
<row>INSERT sysdiagrams(name,principal_id,diagram_id,version,definition) VALUES('ERD2',1,2,1,0xD0CF11E0A1B11AE100000...)</row>
<row>INSERT sysdiagrams(name,principal_id,diagram_id,version,definition) VALUES('ERD3',1,3,1,0xD0CF11E0A1B11AE100000...)</row>
SET IDENTITY_INSERT sysdiagrams OFF;
Remove the row & /row XML tags from your inserts, and run them on the target server. You can truncate the sysdiagrams table if you're replacing all values with new values.

Concurrency problems with temp tables in consequent batches?

I have sometimes a problem when running a script. I have the probelm when using an application (that I didn't write and therefore cannot debug) that launches the scripts. This app isn't returning the full error from SQL Server, but just the error description, so I don't know exactly where th error comes.
I have the error only using this tool (it is a tool that sends the queries directly to SQL Server, using a DAC component), if I run the query manuallyin management studio I don't have the error. (This error moreover occurs only on a particular database).
My query is something like:
SELECT * INTO #TEMP_TABLE
FROM ANOTHER_TABLE
GO
--some other commands here
GO
INSERT INTO SOME_OTHER_TABLE(FIELD1,FIELD2)
SELECT FIELDA, FIELDB
FROM #TEMP_TABLE
GO
DROP TABLE #TEMP_TABLE
GO
The error I get is #TEMP_TABLE is not a valid object
So somehow i suspect that the DROP statement is executed before the INSERT statement.
But AFAIK when a GO is there the next statement is not executed until the previous has been completed.
Now I suspoect that this is not true with temp tables... Or do you have another ideas?
Your problem is most likely caused by either an end of session prior to the DROP TABLE causing SQL Server to automatically drop the table or the DROP TABLE is being executed in a different session than the other code (that created and used the temporary table) causing the table not to be visible.
I am assuming that stored procedures are not involved here, because it looks like you are just executing batches, since local temporary tables are also dropped when a stored proc is exited.
There is a good description of local temporary table behavior in this article on Temporary Tables in SQL Server:
You get housekeeping with Local Temporary tables; they are
automatically dropped when they go out of scope, unless explicitly
dropped by using DROP TABLE. Their scope is more generous than a table
Variable so you don't have problems referencing them within batches or
in dynamic SQL. Local temporary tables are dropped automatically at
the end of the current session or procedure. Dropping it at the end of
the procedure that created it can cause head-scratching: a local
temporary table that is created within a stored procedure or session
is dropped when it is finished so it cannot be referenced by the
process that called the stored procedure that created the table. It
can, however, be referenced by any nested stored procedures executed
by the stored procedure that created the table. If the nested
procedure references a temporary table and two temporary tables with
the same name exist at that time, which table is the query is resolved
against?
I would start up SQL Profiler and verify if your tool uses one connection to execute all batches, or if it disconnects/reconnects. Also it could be using a connection pool.
Anyway, executing SQL batches from a file is so simple that you might develop your own tool very quickly and be better off.

SQL Server equivalent of MySQL Dump to produce insert statements for all data in a table

I have an application that uses a SQL Server database with several instances of the database...test, prod, etc... I am making some application changes and one of the changes involves changing a column from a nvarchar(max) to a nvarchar(200) so that I can add a unique constraint on it. SQL Server tells me that this requires dropping the table and recreating it.
I want to put together a script that will do the table drop, recreate it with the new schema, and then reinsert the data that was there previously all in one go, if possible, just to keep things simple for use when I migrate this change to production.
There is probably a good SQL Server way to do this but I'm just not aware of it. If I was using Mysql I would mysqldump the table and its contents, and use that as my script for applying that change to production. I can't find any export functionality in SQL server that will give me a text file consisting of inserts for all data in a table.
Use SQL Server's Generate Scripts command
right click on the database; Tasks -> Generate Scripts
select your tables, click Next
click the Advanced button
find Types of data to script - choose Schema and Data.
you can then choose to save to file, or put in new query window.
results in INSERT statements for all table data selected in bullet 2.
No need to script
here are two ways
1 use alter table ....alter column.....
example..you have to do 1 column at a time
create table Test(SomeColumn nvarchar(max))
go
alter table Test alter column SomeColumn nvarchar(200)
go
2 dump into a new table while converting the column
select <columns except for the columns you want to change>,
convert(nvarchar(200),YourColumn) as YourColumn
into SomeNewTable
from OldTable
drop old table
rename this table to the same table as the old table
EXEC sp_rename 'SomeNewTable', 'OldTable';
Now add your index

Moving all non-clustered indexes to another filegroup in SQL Server

In SQL Server 2008, I want to move ALL non-clustered indexes in a DB to a secondary filegroup. What's the easiest way to do this?
Run this updated script to create a stored procedure called MoveIndexToFileGroup. This procedure moves all the non-clustered indexes on a table to a specified file group. It even supports the INCLUDE columns that some other scripts do not. In addition, it will not rebuild or move an index that is already on the desired file group. Once you've created the procedure, call it like this:
EXEC MoveIndexToFileGroup #DBName = '<your database name>',
#SchemaName = '<schema name that defaults to dbo>',
#ObjectNameList = '<a table or list of tables>',
#IndexName = '<an index or NULL for all of them>',
#FileGroupName = '<the target file group>';
To create a script that will run this for each table in your database, switch your query output to text, and run this:
SELECT 'EXEC MoveIndexToFileGroup '''
+TABLE_CATALOG+''','''
+TABLE_SCHEMA+''','''
+TABLE_NAME+''',NULL,''the target file group'';'
+char(13)+char(10)
+'GO'+char(13)+char(10)
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
ORDER BY TABLE_SCHEMA, TABLE_NAME;
Please refer to the original blog for more details. I did not write this procedure, but updated it according to the blog's responses and confirmed it works on both SQL Server 2005 and 2008.
Updates
#psteffek modified the script to work on SQL Server 2012. I merged his changes.
The procedure fails when your table has the IGNORE_DUP_KEY option on. No fix for this yet.
#srutzky pointed out the procedure does not guarantee to preserve the order of an index and made suggestions on how to fix it. I updated the procedure accordingly.
ojiNY noted the procedure left out index filters (for compatibility with SQL 2005). Per his suggestion, I added them back in.
Script them, change the ON clause, drop them, re-run the new script. There is no alternative really.
Luckily, there are scripts on the Interwebs such as this one that will deal with scripting for you.
Update: This thing will take long time to do step 2 manually if you are using MS SQL Server manager 2008R2 or earlier. I used sql server manager 2014, so it works well (because the way it export the drop and create index is easy to modify)
I tried to run script in SQL server 2014 and got some issue, I'm too lazy to detect the problems, SO I come up with another solution that not depend on the version of SQL server you are running.
Export your index (with drop and create)
2.Update your script, remove all things related to drop create tables, keep the thing belong to indexs. and Replace your original index with the new index (in my case, I replace ON [PRIMARY] by ON [SECONDARY]
[]5
Run script! And wait until it done.
(You may want to save the script to run in some others environment).

Resources