I am using SQL server MSDE 2000. I have a field called notes of type nvarchar(65).
The content is 'Something ' with an extra space after the content (quotes for clarity) in all the records. I used the following command.
UPDATE TABLE1
SET notes = RTRIM(LTRIM(notes))
But it does not work. Is there any alternate way to do it?
Are you sure the query isn't working? Try:
SELECT TOP 100 '~'+ t.notes +'~'
FROM TABLE1 t
TOP 100 will limit the results to the first 100 rows, enough to get an idea if there's really a space in the output. If there is, and RTRIM/LTRIM is not removing it - then you aren't dealing with a whitespace character. In that case, try:
UPDATE TABLE1
SET notes = REPLACE(notes,
SUBSTRING(notes, PATINDEX('%[^a-zA-Z0-9 '''''']%', notes), 1),
'')
WHERE PATINDEX('%[^a-zA-Z0-9 '''''']%', notes) <> 0
... OR you could literally just copy/paste the blank ' ' (space) at the end of a field as a result of your query into your replace statement and update everything from there.
update TABLE1
set notes = replace(notes, ' ', '')
And just in case you need to TRIM all spaces in all columns, you can use this script to do it dynamically:
--Just change table name
declare #MyTable varchar(100)
set #MyTable = 'MyTable'
--temp table to get column names and a row id
select column_name, ROW_NUMBER() OVER(ORDER BY column_name) as id into #tempcols from INFORMATION_SCHEMA.COLUMNS
WHERE DATA_TYPE IN ('varchar', 'nvarchar') and TABLE_NAME = #MyTable
declare #tri int
select #tri = count(*) from #tempcols
declare #i int
select #i = 0
declare #trimmer nvarchar(max)
declare #comma varchar(1)
set #comma = ', '
--Build Update query
select #trimmer = 'UPDATE [dbo].[' + #MyTable + '] SET '
WHILE #i <= #tri
BEGIN
IF (#i = #tri)
BEGIN
set #comma = ''
END
SELECT #trimmer = #trimmer + CHAR(10)+ '[' + COLUMN_NAME + '] = LTRIM(RTRIM([' + COLUMN_NAME + ']))'+#comma
FROM #tempcols
where id = #i
select #i = #i+1
END
--execute the entire query
EXEC sp_executesql #trimmer
drop table #tempcols
Related
Let the table name is "MyTable"
My current data looks like:
Following, I need after a query on above table:
Actually I need to update all column where value is "NULL", in a single query.
Use ISNULL if you want to see the NULL as 0. Like this
SELECT ISNULL(Column1,0) FROM YourTable
or what you need is to update the value as 0 if NULL and keep the value as it is otherwise. these use a case in the update statement. Like this
Update YourTable
SET Column1 = CASE WHEN Column1 IS NULL THEN 0 ELSE Column1 END,
Column2 = CASE WHEN Column2 IS NULL THEN 0 ELSE Column2 END
and so on for the rest of the columns. Or this is also possible
Update YourTable
SET Column1 = ISNULL(Column1,0),
cOLUMN2 = ISNULL(Column2,0)
You can use something like this.
It is elegant, but it will update all columns in the table. Huge tables might kill the server
DECLARE #TableName sysname = 'tablename'
Declare #UptQuery varchar(max)
Select #UptQuery = stuff(T.X.query('name').value('.', 'varchar(max)'), 1, 1, '')
from
(Select ','+name + '=ISNULL('+name+', 0)' name from
sys.columns where object_id = object_id(#TableName) for xml path(''), type) T(X)
exec ('Update ' + #TableName + ' set ' + #UptQuery)
Old answer
It will go through all columns for a table and update everything with 0 if it is null. It is a lot of updates, and I think it is still better to design the table correctly from the start.
DECLARE #TableName sysname = 'tablename'
Declare #ColName sysname
Select name into #temp from sys.columns where object_id = object_id(#TableName)
while(0 < (Select count(1) from #temp))
BEGIN
SET ROWCOUNT 1
Select #ColName = name from #temp
SET ROWCOUNT 0
exec('Update ' + #TableName + ' set ' + #ColName + ' = ISNULL('+#ColName+', 0) where ' + #ColName + ' is null')
delete #temp where name = #ColName
END
Update table
Set column1 = coalesce (column1,0), ....
declare #tableName varchar(30)
set #tableName='MyTable'
DECLARE #MakeString AS NVARCHAR(MAX)
SELECT #MakeString=
(SELECT cname + ',' AS 'data()'
FROM ( select COLUMN_NAME +'= isnull(['+COLUMN_NAME+'],0)' as cname from INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = #tableName
) as ccc
FOR XML PATH(''))
SET #MakeString = LEFT(#MakeString, LEN(#MakeString) - 1)
DECLARE #Sql AS NVARCHAR(MAX)
set #Sql='Update '+#tableName+'
SET '+#MakeString+''
EXEC(#Sql);
UPDATE Table SET ColumnName1=0 WHERE ColumnName1 IS NULL
...
I want to check if a given table has specific column names, I want it to return true if it has them all and if one column name doesn't exist I want it to return false, this is my query :
SELECT COLUMN_NAME
FROM db.INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'MyTable'
I want to check if these names in the query result:
('UpdatedDate', 'CreatedDate', 'UpdatedBy')
If you know count of list this query help you
SELECT COUNT(COLUMN_NAME)
FROM db.INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'MyTable' AND COLUMN_NAME IN ('UpdatedDate', 'CreatedDate', 'UpdatedBy')
GROUP BY COLUMN_NAME HAVING COUNT(COLUMN_NAME) = 3;
Create a table variable with the column names which we need to check with information_schema.columns. Then do a check between the table variable and information_schema.columns. Not sure how efficient is this.
Query
declare #cols as varchar(max) = 'UpdatedDate,CreatedDate,UpdatedBy';
declare #cols2 as varchar(max) = '(' + char(39);
set #cols2 += replace(#cols, ',', '''),(''') + ''');';
declare #sql as varchar(max) = 'declare #tbl as table([col] varchar(1000));';
set #sql += 'insert into #tbl values' + #cols2;
set #sql += 'declare #tot as int;set #tot = (select count(*) from #tbl);';
set #sql += 'select case when count(*) = #tot
then ''true'' else ''false'' end as [status]
from #tbl t1 where exists(
select 1 from information_schema.columns t2
where t1.[col] = t2.[column_name]
and t2.[table_name] = ''MyTable'');';
exec(#sql);
I need to insert an almost duplicated row into table, while changing few values.
For example insert duplicated row with new id (I don't want automatic id) and different name but all other values the same.
The problem is that I need to make a select *
I know that there is a way to insert from select and changing values this way :
insert into Table1(id,name,surname) select newid(),'David',surname from Table1 where id=1
but I don't want to enlist all fields ,instead I want to use select *, so if fields added I won't have to change my stored procedure.
I want something like :
insert into Table1 (
update (SELECT *
FROM Table1
WHERE id= 1 ) t
set t.id= newid(),name='David')
Is there a way to do it ?
You can use temp hash table to accomplish this.
SELECT *
INTO #temp
FROM Table1
WHERE id= 1;
UPDATE #temp
SET ID = newid(),
Name='David'
INSERT INTO Table1 SELECT * FROM #temp;
Note that the #temp table is automatically dropped when the client disconnect from the DB server.
Also, as previously noted, I prefer to use column names separately instead of *.
Example: SQL Fiddle
The code I use:
declare #table sysname
declare #excludecols nvarchar(max)
declare #uniqueWhereToCopy nvarchar(max)
declare #valuesToChange nvarchar(max)
--copy settings
set #table = 'orsrg' --the tablename
set #excludecols='' --columnnames to exclude from the copy, seperated by commas
set #uniqueWhereToCopy = 'ID=1188'
set #valuesToChange = 'regel='' 4''' --columnName=<value>,columnName2=<value2>, .... (needed for unique indexes)
set #excludecols=#excludecols + ','
set #valuesToChange=#valuesToChange + ','
--get the columnnames to copy
declare #sqlcolumns nvarchar(max)
set #sqlcolumns = ''
SELECT #sqlcolumns = #sqlcolumns + name from
(select '[' + c.name + '], ' as name FROM sys.COLUMNS c inner join sys.objects o
on c.object_id = o.object_id
WHERE o.name = #table
and is_identity = 0 /*exclude identity*/
and is_rowguidcol = 0 /*exclude rowguids*/
and is_computed = 0 /*exclude computed columns*/
and system_type_id <> 189 /*exclude timestamp*/
and charindex(c.name, #excludecols,1) = 0 /*exclude user specified columns*/)q
--get the select columns and values
declare #sqlselectvalues nvarchar(max)
set #sqlselectvalues = #sqlcolumns
while len(#valuesToChange)>1
begin
declare #colValueSet nvarchar(max)
declare #colname sysname
declare #value nvarchar(max)
set #colValueSet = left(#valuesToChange,charindex(',',#valuesToChange,1)-1)
set #valuesToChange = substring(#valuesToChange,charindex(',',#valuesToChange,1)+1,len(#valuesToChange))
set #colname = '[' + left(#colValueSet,charindex('=',#colValueSet,1)-1) +']'
set #value = substring(#colValueSet,charindex('=',#colValueSet,1)+1,len(#colValueSet))
set #sqlselectvalues = REPLACE(#sqlselectvalues,#colname,#value)
end
--remove the last comma
set #sqlcolumns = left(#sqlcolumns, len(#sqlcolumns)-1)
set #sqlselectvalues = left(#sqlselectvalues, len(#sqlselectvalues)-1)
--create the statement
declare #stmt nvarchar(max)
set #stmt = 'Insert into ' + #table + '(' + #sqlcolumns + ') select ' + #sqlselectvalues + ' from ' + #table + ' with (nolock) where ' + #uniqueWhereToCopy
--copy the row
exec sp_executesql #stmt
No, because a SELECT * will always contain the id column.
Generally, you should avoid SELECT * anywhere except when querying interactively. When the stored procedure is compiled, the query text will be parsed and replaced with the correct columns, rendering your stored procedure invalid on every change to the structure anyway.
Could you please advise how to find the number of rows in the table which have 1 or more missing values? The missing values are represented in my table by question marks = '?'. The table has 15 columns and ~50k rows. When I run the following query for some of the columns I can receive some results:
SELECT
COUNT(*)
FROM table_name
WHERE column_name ='?'
However I have also columns which bring me result: "Error converting data type varchar to float"
I would like to be able to find the number of rows in the table which have 1 or more missing values using 1 query/not run separately for each column.
Thank you in advance for your support!
Select Count(*)
From mySchema.myTable
Where Cast(Col1 As NVarChar(128)) +
Cast(Col2 As NVarChar(128)) +
Cast(Coln As NVarChar(128)) Like '%?%'
It's ugly and WILL be slow and you may need to modify the Casts accordingly, but should do the trick.
This should work for any column:
select count(*)
from table_name
where column_name is null or cast(column_name as varchar(255)) = '?';
Try following query:
Just set table name and it will get all columns
Also you can give value_to_match like '?' in your case or any other if you want.
DECLARE #table_name nvarchar(max) = 'table_name'
DECLARE #value_to_match nvarchar(max) = '1'
DECLARE #query nvarchar(max) = ''
DECLARE #Condition nvarchar(max) = ' OR ' -- 1 OR when you want to count row if any column has that value -- 2 when you want all all columns to have same value
SELECT #query = #query + ' cast(' + COLUMN_NAME + ' as nvarchar(500)) = ''' + #value_to_match + '''' + #Condition FROM informatioN_schema.columns WHERE table_name = #table_name
if ##rowcount = 0
BEGIN
SELECT 'Table doesn''t Exists'
RETURN
END
SELECT #query = LEFT(#query,LEN(#query)-3)
PRINT ('select count(9) FROM ' + #table_name + ' WHERE ' + #query)
EXEC ('select count(9) FROM ' + #table_name + ' WHERE ' + #query)
Is there any SQL lingo to return JUST the first two columns of a table WITHOUT knowing the field names?
Something like
SELECT Column(1), Column(2) FROM Table_Name
Or do I have to go the long way around and find out the column names first? How would I do that?
You have to get the column names first. Most platforms support this:
select column_name,ordinal_position
from information_schema.columns
where table_schema = ...
and table_name = ...
and ordinal_position <= 2
There it´s
declare #select varchar(max)
set #select = 'select '
select #select=#select+COLUMN_NAME+','
from information_schema.columns
where table_name = 'TABLE' and ordinal_position <= 2
set #select=LEFT(#select,LEN(#select)-1)+' from TABLE'
exec(#select)
A dynamic query using for xml path will also do the job:
declare #sql varchar(max)
set #sql = (SELECT top 2 COLUMN_NAME + ',' from information_schema.columns where table_name = 'YOUR_TABLE_NAME_HERE' order by ordinal_position for xml path(''))
set #sql = (SELECT replace(#sql +' ',', ',''))
exec('SELECT ' + #sql + ' from YOUR_TABLE_NAME_HERE')
I wrote a stored procedure a while back to do this exact job. Even though in relational theory there is no technical column order SSMS is not completely relational. The system stores the order in which the columns were inserted and assigns an ID to them. This order is followed using the typical SELECT * statement which is why your SELECT statements appear to return the same order each time. In practice its never a good idea to SELECT * with anything as it doesn't lock the result order in terms of columns or rows. That said I think people get so stuck on 'you shouldn't do this' that they don't write scripts that actually can do it. Fact is there is predictable system behavior so why not use it if the task isn't super important.
This SPROC of course has caveats and is written in T-SQL but if your looking to just return all of the values with the same behavior of SELECT * then this should do the job pretty easy for you. Put in your table name, the amount of columns, and hit F5. It returns them in order from left to right the same as you'd be expecting. I limited it to only 5 columns but you can edit the logic if you need any more. Takes both temp and permanent tables.
EXEC OnlySomeColumns 'MyTable', 3
/*------------------------------------------------------------------------------------------------------------------
Document Title: The Unknown SELECT SPROC.sql
Created By: CR
Date: 4.28.2013
Purpose: Returns all results from temp or permanent table when not knowing the column names
SPROC Input Example: EXEC OnlySomeColumns 'MyTable', 3
--------------------------------------------------------------------------------------------------------------------*/
IF OBJECT_ID ('OnlySomeColumns', 'P') IS NOT NULL
DROP PROCEDURE OnlySomeColumns;
GO
CREATE PROCEDURE OnlySomeColumns
#TableName VARCHAR (1000),
#TotalColumns INT
AS
DECLARE #Column1 VARCHAR (1000),
#Column2 VARCHAR (1000),
#Column3 VARCHAR (1000),
#Column4 VARCHAR (1000),
#Column5 VARCHAR (1000),
#SQL VARCHAR (1000),
#TempTable VARCHAR (1000),
#PermanentTable VARCHAR (1000),
#ColumnNamesAll VARCHAR (1000)
--First determine if this is a temp table or permanent table
IF #TableName LIKE '%#%' BEGIN SET #TempTable = #TableName END --If a temporary table
IF #TableName NOT LIKE '%#%' BEGIN SET #PermanentTable = #TableName END --If a permanent column name
SET NOCOUNT ON
--Start with a few simple error checks
IF ( #TempTable = 'NULL' AND #PermanentTable = 'NULL' )
BEGIN
RAISERROR ( 'ERROR: Please select a TempTable or Permanent Table.',16,1 )
END
IF ( #TempTable <> 'NULL' AND #PermanentTable <> 'NULL' )
BEGIN
RAISERROR ( 'ERROR: Only one table can be selected at a time. Please adjust your table selection.',16,1 )
END
IF ( #TotalColumns IS NULL )
BEGIN
RAISERROR ( 'ERROR: Please select a value for #TotalColumns.',16,1 )
END
--Temp table to gather the names of the columns
IF Object_id('tempdb..#TempName') IS NOT NULL DROP TABLE #TempName
CREATE TABLE #TempName ( ID INT, Name VARCHAR (1000) )
--Select the column order from a temp table
IF #TempTable <> 'NULL'
BEGIN
--Verify the temp table exists
IF NOT EXISTS ( SELECT 1
FROM tempdb.sys.columns
WHERE object_id = object_id ('tempdb..' + #TempTable +'') )
BEGIN
RAISERROR ( 'ERROR: Your TempTable does not exist - Please select a valid TempTable.',16,1 )
RETURN
END
SET #SQL = 'INSERT INTO #TempName
SELECT column_id AS ID, Name
FROM tempdb.sys.columns
WHERE object_id = object_id (''tempdb..' + #TempTable +''')
ORDER BY column_id'
EXEC (#SQL)
END
--From a permanent table
IF #PermanentTable <> 'NULL'
BEGIN
--Verify the temp table exists
IF NOT EXISTS ( SELECT 1
FROM syscolumns
WHERE id = ( SELECT id
FROM sysobjects
WHERE Name = '' + #PermanentTable + '' ) )
BEGIN
RAISERROR ( 'ERROR: Your Table does not exist - Please select a valid Table.',16,1 )
RETURN
END
SET #SQL = 'INSERT INTO #TempName
SELECT colorder AS ID, Name
FROM syscolumns
WHERE id = ( SELECT id
FROM sysobjects
WHERE Name = ''' + #PermanentTable + ''' )
ORDER BY colorder'
EXEC (#SQL)
END
--Set the names of the columns
IF #TotalColumns >= 1 BEGIN SET #Column1 = (SELECT Name FROM #TempName WHERE ID = 1) END
IF #TotalColumns >= 2 BEGIN SET #Column2 = (SELECT Name FROM #TempName WHERE ID = 2) END
IF #TotalColumns >= 3 BEGIN SET #Column3 = (SELECT Name FROM #TempName WHERE ID = 3) END
IF #TotalColumns >= 4 BEGIN SET #Column4 = (SELECT Name FROM #TempName WHERE ID = 4) END
IF #TotalColumns >= 5 BEGIN SET #Column5 = (SELECT Name FROM #TempName WHERE ID = 5) END
--Create a select list of only the column names you want
IF Object_id('tempdb..#FinalNames') IS NOT NULL DROP TABLE #FinalNames
CREATE TABLE #FinalNames ( ID INT, Name VARCHAR (1000) )
INSERT #FinalNames
SELECT '1' AS ID, #Column1 AS Name UNION ALL
SELECT '2' AS ID, #Column2 AS Name UNION ALL
SELECT '3' AS ID, #Column3 AS Name UNION ALL
SELECT '4' AS ID, #Column4 AS Name UNION ALL
SELECT '5' AS ID, #Column5 AS Name
--Comma Delimite the names to insert into a select statement. Bracket the names in case there are spaces
SELECT #ColumnNamesAll = COALESCE(#ColumnNamesAll + '], [' ,'[') + Name
FROM #FinalNames
WHERE Name IS NOT NULL
ORDER BY ID
--Add an extra bracket at the end to complete the string
SELECT #ColumnNamesAll = #ColumnNamesAll + ']'
--Tell the user if they selected to many columns
IF ( #TotalColumns > 5 AND EXISTS (SELECT 1 FROM #FinalNames WHERE Name IS NOT NULL) )
BEGIN
SELECT 'This script has been designed for up to 5 columns' AS ERROR
UNION ALL
SELECT 'Only the first 5 columns have been selected' AS ERROR
END
IF Object_id('tempdb..#FinalNames') IS NOT NULL DROP TABLE ##OutputTable
--Select results using only the Columns you wanted
IF #TempTable <> 'NULL'
BEGIN
SET #SQL = 'SELECT ' + #ColumnNamesAll + '
INTO ##OutputTable
FROM ' + #TempTable + '
ORDER BY 1'
EXEC (#SQL)
END
IF #PermanentTable <> 'NULL'
BEGIN
SET #SQL = 'SELECT ' + #ColumnNamesAll + '
INTO ##OutputTable
FROM ' + #PermanentTable + '
ORDER BY 1'
EXEC (#SQL)
END
SELECT *
FROM ##OutputTable
SET NOCOUNT OFF
SQL doesn't understand the order of columns. You need to know the column names to get them.
You can look into querying the information_schema to get the column names. For example:
SELECT column_name
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = 'tbl_name'
ORDER BY ordinal_position
LIMIT 2;
You can query the sysobject of the table to find out the first two column then dynamically generate the SQL statement you need.
If you want a permant object that you can query over and over again make a view for each table that only returns the first 2 columns. You can name the columns Column1 and Column2 or use the existing names.
If you want to return the first two columns from any table without any preprocessing steps create a stored procedure that queries the system information and executes a dynamic query that return the first two columns from the table.
Or do I have to go the long way around and find out the column names first? How would I do that?
It's pretty easy to do manually.
Just run this first
select * from tbl where 1=0
This statement works on all major DBMS without needing any system catalogs.
That gives you all the column names, then all you need to do is type the first two
select colname1, colnum2 from tbl