SQL Server Management Studio - Query using text file - sql

Let's say I have a text file that has the following lines
102
333
534
Then, in my SQL table, I have a few different columns:
AutoID | Name | Description
--------------------------------------
102  | Jackson  | [Description Here]
241  | Edward   | [Description Here]
333  | Timothy  | [Description Here]
437  | Nikky    | [Description Here]
534  | Jeremy   | [Description Here]
Is there anyway I can parse the text file through SQL Server Management Studio so that it will query the table and pull out every row that has a column (AutoID, in this case) that matches a line in the text file (Note, I only want the rows from a table that I would specify)?
This way I could edit them or update the rows that only match IDs in the text file.
The rows displayed in management studio would look like this.
 AutoID | NAME  | Description
--------------------------------------
102  | Jackson  | [Description Here]
333  | Timothy  | [Description Here]
534  | Jeremy   | [Description Here]

--What you need to do is import the text file into a table in your SQL database, and then compare its values to the table you want to query (which I have called AutoIDTest in my example).
--Using your example data, I've put together the following code that accomplishes this process.
--1. I created a destination table for the text file's values called TextImport. I've called the test text file E:\TestData.txt. Additionally, I'm assuming this text file only has one column, autoID.
--2. Then, I imported the data into the destination table using the BULK INSERT statement.
--3. Finally, I compared the data in TextImport to the table from which you are seeking values using an INNER JOIN statement.
CREATE TABLE AutoIDTest ---Create test table. Since your first column doesn't have a name, I'm calling it ID. I'm assuming AutoID and ID are both of type int.
(
ID int,
AutoID int,
Name varchar(25),
Description varchar(50)
)
INSERT INTO AutoIDTest -- Populate test table
VALUES
( 1, 102, 'Jackson', 'Description1'),
( 2, 241, 'Edward', 'Description2'),
( 3, 333, 'Timothy', 'Description3'),
( 4, 437, 'Nikky', 'Description4'),
( 5, 534, 'Jeremy', 'Description5')
CREATE TABLE TextImport --Create destination table for text file.
(
AutoID varchar(20),
)
BULK INSERT TextImport --Load Data from text file into TextImport table
FROM 'E:\TestData.txt' ---The name and location of my test text file.
WITH
(
ROWTERMINATOR ='\n'
);
SELECT ---Produce Output Data
ID,
t1.AutoID,
Name,
Description
FROM
AutoIDTest AS t1
INNER JOIN
TextImport AS t2
ON t1.autoID = cast(t2.autoID AS int) --convert varchar to int
OUTPUT
-- ID AutoID Name Description
-- --------- ----------- ------------------------- -------------------
-- 1 102 Jackson Description1
-- 3 333 Timothy Description3
-- 5 534 Jeremy Description5

Related

SQL - Replace a particular part of column string value (between second and third slash)

In my SQLServer DB, I have a table called Documents with the following columns:
ID - INT
DocLocation - NTEXT
DocLocation has values in following format:
'\\fileShare1234\storage\ab\xyz.ext'
Now it seems these documents are stored in multiple file share paths.
We're planning to migrate all documents in one single file share path called say 'newFileShare' while maintaining the internal folder structure.
So basically '\\fileShare1234\storage\ab\xyz.ext' should be updated to '\\newFileShare\storage\ab\xyz.ext'
Two questions:
How do I query my DocLocation to extract DocLocations with unique file share values? Like 'fileShare1234' and 'fileShare6789' and so on..
In a single Update query how do I update my DocLocation values to newFileShare ('\\fileShare1234\storage\ab\xyz.ext' to '\\newFileShare\storage\ab\xyz.ext')
I think the trick would be extract and replace text between second and third slashes.
I've still not figured out how to achieve my first objective. I require those unique file shares for some other tasks.
As for the second objective, I've tried using replace between it will require multiple update statements. Like I've done as below:
update Documents set DocLocation = REPLACE(Cast(DocLocation as NVarchar(Max)), '\\fileShare1234\', '\\newFileShare\')
The first step is fairly easy. If all your paths begin with \\, then you can find all the DISTINCT servers using SUBSTRING. I will make a simple script with a table variable to replicate some data. The value of 3 is in the query and it is the length of \\ plus 1 since SQL Server counts from 1.
DECLARE #Documents AS TABLE(
ID INT NOT NULL,
DocLocation NTEXT NOT NULL
);
INSERT INTO #Documents(ID, DocLocation)
VALUES (1,'\\fileShare56789\storage\ab\xyz.ext'),
(2,'\\fileShare1234\storage\ab\cd\xyz.ext'),
(3,'\\share4567890\w\x\y\z\file.ext');
SELECT DISTINCT SUBSTRING(DocLocation, 3, CHARINDEX('\', DocLocation, 3) - 3) AS [Server]
FROM #Documents;
The results from this are:
Server
fileShare1234
fileShare56789
share4567890
For the second part, we can just concatenate the new server name with the path that appears after the first \.
UPDATE #Documents
SET DocLocation = CONCAT('\\newfileshare\',
SUBSTRING(DocLocation, 3, LEN(CAST(DocLocation AS nvarchar(max))) - 2));
SELECT * FROM #Documents;
For some reason I cannot create a table with the results here, but the values I see are this:
\\newfileshare\fileShare56789\storage\ab\xyz.ext
\\newfileshare\fileShare1234\storage\ab\cd\xyz.ext
\\newfileshare\share4567890\w\x\y\z\file.ext
Please try the following solution based on XML and XQuery.
Their data model is based on ordered sequences. Exactly what we need while processing fully qualified file path: [position() ge 4]
When you are comfortable, just run the UPDATE statement by updating the DocLocation column with the calculated result.
It is better to use NVARCHAR(MAX) instead of NText data type.
SQL
-- DDL and sample data population, start
DECLARE #tbl AS TABLE(ID INT IDENTITY PRIMARY KEY, DocLocation NVARCHAR(MAX));
INSERT INTO #tbl(DocLocation) VALUES
('\\fileShare56789\storage\ab\xyz.ext'),
('\\fileShare1234\storage\ab\cd\xyz.ext'),
('\\share4567890\w\x\y\z\file.ext');
-- DDL and sample data population, end
DECLARE #separator CHAR(1) = '\'
, #newFileShare NVARCHAR(100) = 'newFileShare';
SELECT ID, DocLocation
, result = '\\' + #newFileShare + #separator +
REPLACE(c.query('data(/root/r[position() ge 4]/text())').value('text()[1]', 'NVARCHAR(MAX)'), SPACE(1), #separator)
FROM #tbl
CROSS APPLY (SELECT TRY_CAST('<root><r><![CDATA[' +
REPLACE(DocLocation, #separator, ']]></r><r><![CDATA[') +
']]></r></root>' AS XML)) AS t(c);
Output
+----+---------------------------------------+--------------------------------------+
| ID | DocLocation | result |
+----+---------------------------------------+--------------------------------------+
| 1 | \\fileShare56789\storage\ab\xyz.ext | \\newFileShare\storage\ab\xyz.ext |
| 2 | \\fileShare1234\storage\ab\cd\xyz.ext | \\newFileShare\storage\ab\cd\xyz.ext |
| 3 | \\share4567890\w\x\y\z\file.ext | \\newFileShare\w\x\y\z\file.ext |
+----+---------------------------------------+--------------------------------------+
to get the unique list of shared folder path , you can use this query:
SELECT distinct SUBSTRING(DocLocation,0,CHARINDEX('\',DocLocation,3))
from Documents
and your update command should work and yes you can merge copuple of replace update but better to run them seperately
update Documents
set DocLocation = REPLACE(DocLocation,'\\fileShare1234','\\newFileShare')
but I recommend you always record relative address instead of full path like: \storage\ab\xyz.ext'

How can I create an external table using textfile with presto?

I've a csv file in hdfs directory /user/bzhang/filefortable:
123,1
And I use the following to create an external table with presto in hive:
create table hive.testschema.au1 (count bigint, matched bigint) with (format='TEXTFILE', external_location='hdfs://192.168.0.115:9000/user/bzhang/filefortable');
But when I run select * from au1, I got
presto:testschema> select * from au1;
count | matched
-------+---------
NULL | NULL
I changed the comma to the TAB as the delimeter but it still returns NULL. But If I modify the csv as
123
with only 1 column, the select * from au1 gives me:
presto:testschema> select * from au1;
count | matched
-------+---------
123 | NULL
So maybe I'm wrong with the file format or anything else?
I suppose the field delimiter of the table is '\u0001'.
You can change the ',' to '\u0001' or change the field delimiter to ',' , and check your problem was solved

How to Copy data from XML Column and Insert it into a Table which Contains column names same as XML Tag Names in MS SQL SERVER

Say If I have Table which contains Single Column of XML datype
Eg:
Details(Column Name in Table)
<emp>--row1 in that column
<Name>Alice</name>
<ID>1</ID>
</emp>
<emp>--row2 in that column
<Name>Bob</name>
<ID>2</ID>
</emp>
Now I need to read this column from the table and insert it on to another table which contains same column names as the XML Tag names i.e
Emp
Name ID
Alice 1
Bob 2
I have tried OPENXML ,XQUERY etc . Nothing Seems to work to read column by column and insert into that row . Can you please guide me on this?
A CROSS APPLY on the xml field with the original table should give you the output you need to insert into the target table.
DECLARE #Source TABLE (XmlData XML)
DECLARE #Emp TABLE (ID INT, Name VARCHAR(15))
INSERT #Source VALUES
('<emp><Name>Alice</Name><ID>1</ID></emp><emp><Name>Bob</Name><ID>2</ID></emp>'),
('<emp><Name>Max</Name><ID>3</ID></emp>')
INSERT #Emp (ID, Name)
SELECT
Employees.Emp.value('ID[1]', 'INT') AS ID,
Employees.Emp.value('Name[1]', 'VARCHAR(25)') AS Name
FROM #Source SRC
CROSS APPLY SRC.XmlData.nodes('/emp') AS Employees(Emp)
SELECT * FROM #Emp
The output from the target table in the example above is below. I added a second record to show how 3 xml "emp" elements across only 2 SQL rows correctly insert 3 target records.
ID Name
----------- ---------------
1 Alice
2 Bob
3 Max
I think you can do this.
declare #str_xml xml --- xml data from your column table
SELECT
[Table].[Column].value('name[1]', 'varchar(100)') as ' Name ',
[Table].[Column].value('ID[1]', 'varchar(20)') as ' ID '
FROM #str_xml.nodes('/ emp') as [Table]([Column])
Note :
name[1] = name on this must be same with tag <name> not <Name>
when you can make output table from xml string you can use it to insert into another table.
http://programcall.com/11/dotnet/how-to-read-data-from-xml-string--and-insert-to-table-sql-server.aspx

How to remove Header in csv file generated by sql command

I am working on sql script for getting data from database to csv file,for that i created batch file.when i run batch file it genarated below table as a result
but with result is showing with some dummy data like "Changed database context to 'KMSSource'." and "(1 rows affected)". I want only table and not "Changed database context to 'KMSSource'." and "(1 rows affected)".
I'm using this code
Note:This is sql server query.
create TABLE TempTable
(
IBS_Total int,
IBS_Active int,
IBS_InActive int,
IBS_Only int,
KMS_Active int,
KMS_InActive int
)
INSERT INTO TempTable (IBS_Total,IBS_Active,IBS_InActive,IBS_Only,KMS_Active,KMS_InActive)
select (#IBS_Active+#IBS_INActive),#IBS_Active,#IBS_INActive,#KMS_DEVICENR,#KMS_Active,#KMS_OnlyTotal;
drop table #KMS_DEU
USE [KMSSource]
select * from TempTable
go
and I'm getting this result
**Changed database context to 'KMSSource'.**
IBS_Total IBS_Active IBS_InActive IBS_Only KMS_Active KMS_InActive
----------- ----------- ------------ ----------- ----------- ------------
41621 8632 32989 74 11916 3358
**(1 rows affected)**
BatchfileCode is :-->
#echo off
echo script executing....
:begin
sqlcmd -S%server% -b -i"Data\Report_IBS_KMS_KU_DUE.sql" -o"Extract\Report_IBS_KMS_KU_DUE.csv"
:end
Exit %ERRORLEVEL%
If you are getting an error when removing the USE statement, then you need to qualify the table names in the query, as below. Also be setting NO COUNT ON, you will get the message about rows affected.
SET NOCOUNT ON
CREATE TABLE KMSSource.dbo.TempTable
( IBS_Total INT, IBS_Active INT, IBS_InActive INT, IBS_Only INT, KMS_Active INT, KMS_InActive INT )
INSERT INTO KMSSource.dbo.#KMS_DEU
( IBS_Total, IBS_Active, IBS_InActive, IBS_Only, KMS_Active, KMS_InActive )
SELECT ( #IBS_Active + #IBS_INActive ), #IBS_Active, #IBS_INActive, #KMS_DEVICENR, #KMS_Active, #KMS_OnlyTotal;
DROP TABLE KMSSource.dbo.#KMS_DEU

Insert a empty string on SQL Server with BULK INSERT

Example table contains the fields Id (the Identity of the table, an integer); Name (a simple attribute that allows null values, it's a string)
I'm trying a CSV that contains this:
1,
1,""
1,''
None of them gives me a empty string as the result of the bulk insertion. I'm using SQL Server 2012.
What can I do?
As far as I know, bulk insert can't insert empty string, it can either keep null value or use default value with keepnulls option or without keepnulls option. For your 3 sample records, after insert database, it should be like:
| id | name
| 1 | NULL
| 1 | ""
| 1 | ''
The reason is, the bulk insert will treat your first row, second column value as null; for other 2 rows, will take the second column value as not null, and take it as it is. Instead of let Bulk Insert to insert empty string value for you, you can let you table column having default value as empty string.
Example as following:
CREATE TABLE BulkInsertTest (id int, name varchar(10) DEFAULT '')
Bulk Insert same CSV file into table
BULK INSERT Adventure.dbo.BulkInsertTest
FROM '....\test.csv'
WITH
(
FIELDTERMINATOR ='\,',
ROWTERMINATOR ='\n'
)
SELECT * FROM BulkInsertTest
The result will be like following: (The first row in your CSV will get an empty string)
| id | name
| 1 |
| 1 | ""
| 1 | ''
Please bear in mind that the specified DEFAULT value will only get inserted if you are not using the option KEEPNULLS.
Using the same example as above, if you add the option KEEPNULLS to the BULK INSERT, i.e.:
BULK INSERT BulkInsertTest
FROM '....\test.csv'
WITH
(
FIELDTERMINATOR ='\,',
ROWTERMINATOR ='\n',
KEEPNULLS
)
will result in the default column value being ignored and NULLs being inserted fro empty strings, i.e:
SELECT * FROM BulkInsertTest
will now give you:
id name
1 NULL
1 ""
1 ''
There does not seem to be a good reason to add KEEPNULLS this in your example, but I came across a similar problem just now, where KEEPNULLS was required in the BULK INSERT.
My solution was to define make the column [name] in the staging table BulkInsertTest NOT NULL but remember that the DEFAULT column value gets ignored and an empty string gets inserted instead.
See more here : Keep Nulls or UseDefault Values During Bulk Import (SQL Server)