I’m selecting data on an old database which has an abused status column. The status column has multiple pieces of information in it. Values are like ‘New Contact YYYY’, ‘Online YYYY’, ‘Updated YYYY’, ‘Withdrawn YYYY’, etc…. As you may have guessed, YYYY represents the year … which I need.
In the past I’ve done something similar to
Rtrim( ltrim( Replace(Replace(Replace(Replace(Replace( …
Basically, replacing all text values with an empty string, so the only thing that still exists is the year. I can still do this, but I’m thinking this is ridiculous, and there’s got to be a better way.
Does anybody know of a better way to do this?
If you simply want to extract a four digit year from the string, you could use PATINDEX
SELECT SUBSTRING(FieldName, PATINDEX('%[0-9][0-9][0-9][0-9]%', FieldName), 4)
FROM TableName
If the year allways are the last 4:
SELECT right(FieldName,4) from table
All the answers given solve your problem, but the correct answer is to normalize your data base better. If you need the year as a separate item, it should be stored in a separate column.
Anything else is just removing hairs from a wart, as my dear old grandma used to say (she never actually said that, I just thought of it and it sounded kind of cool - must be why I don't get out much :-).
Related
I have to truncate the first couple of digits out of a Guid on a table. Is it possible to do it only using a SQL script? Or I have to do it programatically?
Thanks!
To answer the direct question at hand (and assume the column's name is foo):
foo is uniqueidentifier:
SELECT substring(convert(nvarchar(50), foo), 3)
foo is simply a string:
SELECT substring(foo, 3)
3 is just an arbitrary starting offset to remove the first "few" characters.
With that said, this sounds like of like an XY problem. If you're running into an issue where you feel you need to truncate the first few characters, it would be important to list that information in your question as well as what you've described sounds like an odd request. However, you're also entitled to have odd requests.
The previous answer was perfectly good. Another option is to use the wonderful RIGHT function. Assuming the Guid is a a uniqueidentifier, then it has 36 characters in it. Just use RIGHT(theguid, 34), e.g.
declare #temp as uniqueidentifier = newid();
select right(#temp, 34);
Hi Having a syntax issue - at least I think it is. I want a default date as part of a case statement inside a materialised view (MS SQL 2008 +):
, CASE
WHEN WithFirstDate = 0 THEN CONVERT(DATE,'1900-JAN-1', 101)
WHEN WithFirstDate = 1 THEN
Start1
ELSE --WithFirstDate = 2
Start2
END ValidDate
I'm getting the following error:
view uses an implicit conversion from string to datetime or smalldatetime. Use an explicit CONVERT with a deterministic style value
I'd like to have a solution that works irrespective of localization (i.e US style dates, Japanese style dates and the rest of the world)
Thanks
Instead of:
CONVERT(DATE,'1900-JAN-1', 101)
Just do:
CONVERT(DATE,'1900-01-01')
However the issue may be with the other two columns, Start1 and Start2. I am guessing these are not DATE columns.
The 101 code you are passing the CONVERT function does not match your format. Check the following link to find the correct code:
http://msdn.microsoft.com/en-us/library/ms187928.aspx
Ok well this forum has gone downhill IMHO, first my post get endless edited for grammar which doesn't change the meaning, then it gets voted down presumably because it was "to difficult" to answer. https://stackoverflow.com/users/61305/aaron-bertrand was on the right lines. Thanks Aaron. The problem was a computed column in one of the referenced tables was non deterministic. This error only resolved in a flag when the materialising clustered index was being created on the view. I'd post a link to the full answer but not allowed. Shame I cant recover all my old badges and points from a couple of years ago. Full answer here http://tinyurl.com/knor8qk
A database that a client of mine has was hacked. I am in the process of trying to rebuild the data. The site is running classic ASP with a SQL Server database. I believe I have found where the weak point was for the hackers and removed that entry point for now.
Every text colummn in the database was appended with some html markup and inline script/js tags.
Here is an example of a field:
all</title><script>
document.write("<style>.aq21{position:absolute;clip:rect(436px,auto,auto,436px);}</style>");
</script>
<div class=aq21>
<a href=http://samedaypaydayloansonlineelqmt.com >same day payday loans online</a>
<a href=http://samedaypaydayloan
This example was in the Users table in the UserRights column. The initial value was all, but then you can see the links that were appended.
I need to write a regex script that will search through all fields in each column of each table in the database and remove this extra markup.
Essentially, if I try to match </table>, then that string and everything that appends it can be replaced with a blank string.
All of these appended strings are the same for each field in the same column. However, there are multiple columns in each table.
This is what I have been doing so far, replacing the hacked part, but a nice regex would probably help me out, though my regex skills.... well suck.
UPDATE [databasename.[db].[databasetable]
set
UserRights = replace(UserRights,'</title><script>document.write("<style>.aq21{position:absolute;clip:rect(436px,auto,auto,436px);}</style>");</script><div class=aq21><a href=http://samedaypaydayloansonlineelqmt.com >same day payday loans online</a><a href=http://samedaypaydayloan','');
Any regex help and/or tips are appreciated.
This is what I ended up doing (big thanks to #Bohemian):
I went through each table and checked which column was affected. Then I ran the following script on each column:
UPDATE [tablename]
set columnname = substring(columnname, 1, charindex('/', columnname)-1)
where columnname like '%</%';
If the column had any markup in it, then I ended up manually updating those records manually. (lucky for me there was only a couple of records).
If anyone has any better solutions, please feel free to comment.
Thanks!
Since the bad stuff starts with a <, and that is an unusual character to typically find, I would use normal text functions, something like this:
update mytable set
mycol = substr(mycol, 1, charindex('<', mycol) - 1)
where mycol like '%<%';
And methodically do this with every column of every table.
Note that I'm only guessing at the right function to use, since I'm unfamiliar with SQL Server, but you get idea.
I welcome someone editing the SQL to improve it.
I need to store schedule date and times. Scheduale contains one date field and two time fields.
Is there any possibility to store schedule in one db field and not in two (datetime + datetime)?
I am using SQL Server 2005.
Thanks!
Whether it is "start"+"stop", or "start"+""duration", you have 2 pieces of information = store 2 pieces of information.
Using a string or XML makes no sense: this requires take more space, more processing, more code to search and use.
Why would you want to store what are effectively two datetimes in one field rather than two? Are there no cases where the schedule might have times that cross days? (ie. 01/03/2011 23:59, 02/03/2011 01:35)? Do you not mind having to parse out the information rather than having it immediately ready for query?
If you really want to, there's no reason you can't store it as a string type, comma separated possibly, maybe XML as suggested, but I can't say it's recommended as date/time fields are more space efficient, nice and fast/flexible for searching purposes, and there are many useful T-SQL functions which can easily be used on date/time types which you'd be hard pushed to use on a string without some parsing and casting/converting.
If you can come up with a good reason for not using two datetime fields, I'll have another Donut! (ps. happy Fat Thursday).
One quick, and horribly evil thought ... you could use part of the datetime to store the "difference" ... sneak it into the "seconds" and "milliseconds" values, and apply it to the main date/time to get the new value. A bit hacky, but it'd could do the job, depending on your range requirements.
-- Example: 01/03/2011 12:30:02
-- Translates into - first of March 2011, 12:30 to 14:30 (12:30 + (seconds * hours))
set #ModifiedDatetime =
DATEADD(hour, DATEPART(second, #originalDateTime), #originalDateTime);
Beware of rounding errors with milliseconds ... and please think about the consequences of what you're doing. God kills a kitten each time someone abuses a type :)
You can try using the XML field type and store an XML snippet in there, similar to the following:
<schedule date="2011-01-01" fromTime="12:00" toTime="14:00" />
You can then use XQuery in a select to transform the result set back to a "normal" row-based result set. A sample query implementing XQuery, based on my example's XML schema, could be as follows:
SELECT
[...]
, Schedule.value('(/schedule/#date)[1]','datetime') as [Date]
, Schedule.value('(/schedule/#fromTime)[1]','char(5)') as [FromTime]
, Schedule.value('(/schedule/#toTime)[1]','char(5)') as [ToTime]
FROM [TABLE]
I'm not saying that storing it as XML is the best way to do it (as the other answers rightfully state), but you asked IF it is possible and I propose a solution...
For those of you who have actually delt with RETS may be able to give me a hand here. The problem occurs when multiple properties are tied into the RETS data even though the property is sold. Basically what I need is to be able to check the database with the SELECT statement against three fields. The fields in question would be C_StreetName, C_StreetNumber, and C_PostalCode.
To make this clear what I want is some type of way to check for duplicates while gathering the dataset, this can't be done in php because of how the data is returned through the application. So if it finds another record with the same C_StreetName, C_StreetNumber, and C_PostalCode it will remove them from the dataset. Ideally it would be nice if it could also check the Status of the two to find out if one is Expired or Sold before removing them from the data.
I'm not familiar with complex SQL functions, I was looking at the IF statement until I found that can only be used while storing data not the other way around. And the CASE statement but it just doesn't seem like that would work.
If you guys have any suggestions on what I should use I'd appreciate it. Hopefully there is a way to do this and keep in mind this is only one table I am accessing I don't have any Joins.
Thanks in advance.
Here's something to get you going in the right direction. I haven't tested this, and am not sure you can nest a case expression inside max() in mysql.
What this accomplishes is to output one row per unique combination of street name, number and postcode, with a status of 'Expired' or 'Sold' taking precedence over other values. That is, if there's a row with 'Expired' it will be output in preference to non-expired and non-sold, and a row with 'Sold' will be output if it exists, regardless of what other rows exist for that property. The case statement just converts the status codes into something orderable.
select
C_StreetName,
C_StreetNumber,
C_PostalCode,
max(
case status
when 'Expired' then 1
when 'Sold' then 2
else 0
end) as status
group by
C_StreetName,
C_StreetNumber,
C_PostalCode;