Gettiing Year from another table - sql-server-2008

I have a field named 'SALARY ON' in which data(year-month) entered is in format '2012-01'(datatype varchar) in table named Table1.For creating a sp i need to take only 2012 from above mentioned table field. How can I do this.
Please help me to solve this.

In the simplest case, a 'SUBSTRING' and 'CAST' will do it for you:
SELECT CAST(SUBSTRING([SALARY ON], 1, 4) AS INT) FROM SALARY
This depends in the fact that the date has been entered in the format YYYY-MM. If you're checking this in a constraint, then the above sample will be fine. Otherwise, you'll need to do some pattern checking before you try to convert it:
SELECT CASE WHEN [SALARY ON] LIKE '[0-9][0-9][0-9][0-9]-[0-9][0-9]' THEN SUBSTRING([SALARY ON], 1, 4) AS INT) ELSE -1 END
You can then take all of the years returned as -1 and raise an error to the user, filter them out, write them to a log file, etc, depending on the environment in which the sp is being called.

Related

MySQL Stored Procedure with Parameters for Recursive CTE

I'm working on a MySQL Way of printing an "affiliate tree" and got the thing working with Common Table Expression. I'm using the following code right now:
WITH RECURSIVE recUsers AS
(
SELECT ID, username, sponsorID, 1 AS depth, username AS path
FROM users
WHERE id = 1
UNION ALL
SELECT c.ID, c.username, c.sponsorID, sc.depth + 1, CONCAT(sc.path, ' > ', c.username)
FROM recUsers AS sc
JOIN users AS c ON sc.ID = c.sponsorID
)
SELECT * FROM recUsers;
This selects the tree underneath the user with the id 1.
Now what I'd need to get is a way to pass that id as a parameter, so I don't need to define everything from the beginning every time I want to get the result.. So my idea is to put everything in a stored prodecure and pass the id in as a parameter.. However, so far I didn't get it working and always getting various errors that are very self speaking...
Basically what I've tried was
DELIMITER //
CREATE PROCEDURE getAffiliateTree(IN userid INT())
BEGIN
---my code here, the userid 1 replaced with userid
END//
DELIMITER;
However, this doesn't seem to work.. How can I get this done?
Two things I would suggest:
Use INT, not INT(). The optional length argument to integer types is deprecated in MySQL 8.0 (which I know you're using, because you're using CTE syntax). Even if you did use the length argument, using an empty argument is not legal syntax.
Make sure that the userid input parameter name is distinct from all of the columns in the tables you reference. That is, if the table has a column named userid (any capitalization), then change the name of your input parameter. Otherwise you may make ambiguous expressions like:
... WHERE userid = userid
Even though you intend one of these to be the column and the other to be the parameter, the SQL parser has no way of knowing that. It ends up treating both as the column name, so it's trivially true on all rows of the table.
Actually, a third thing I would suggest: when you ask questions, "it doesn't seem to work" isn't clear enough. Did it produce an error? If so, what was the full error message? Did it produce no error, but didn't give you the result you wanted? If so, show a mocked-up example of what you expected, and what the query produced that didn't match. It helps to be as clear as you can when you post questions, so readers don't have to guess what trouble you need help with.

Is there a way to change the default date input format

I have a source of data from where I extract some fields, among the fields there are some date fields and the source sends their values like this
#DD/MM/YYYY#
almost all the fields can be sent into the query with no modificaction, except this of course.
I have written a program the gets the data from an internet connection and sends it to the MySQL server and it's sending everything as it should, I am sure because I enabled general logging in the MySQL server and I can see all the queries are correct, except the ones with date fields.
I would like to avoid parsing the fields this way because it's a lot of work since it's all written in c, but if there is no way to do it, I understand and would accept that as an answer of course.
As an example suppose we had the following
INSERT INTO sometable VALUES ('#12/10/2015#', ... OTHER_VALUES ..., '#11/10/2015#');
in this case I send the whole thing as a query using mysql_query() from libmysqlclient.
In other cases I can split the parts of the message in something that is like an instruction and the parameters, something like this
iab A,B,C,#12/10/2015#,X,Y,#11/10/2015#
which could mean INSERT INTO table_a_something_b_whatever VALUES, and in this situation of course, I capture all the parameters and send a single query with a list of VALUES in it. Also in this situation, it's rather simple because I can handle the date like this
char date[] = "#11/10/2015#";
int day;
int month;
int year;
if (sscanf(date, "#%d/%d/%d#", &day, &month, &year) == 3)
{
/* it's fine, build a sane YYYY-MM-DD */
}
So the question is:
How can I tell the MySQL server in what format the date fields are?
Clarification to: Comment 1
Not necessarily INSERT, it's more complex than that. They are sometimes queries with all their parameters in it, sometimes they are just the parameters and I have to build the query. It's a huge mess but I can't do anything about it because it's a paid database and I must use it for the time being.
The real problem is when the query comes from the source and has to be sent as it is, because then there can be many occurrences. When I split the parameters one by one there is no real problem because parsing the above date format and generating the appropriate value of MySQL is quite simple.
You can use STR_TO_DATE() in MySQL:
SELECT STR_TO_DATE('#08/10/2015#','#%d/%m%Y#');
Use this as part of your INSERT process:
INSERT INTO yourtable (yourdatecolumn) VALUES (STR_TO_DATE('#08/10/2015#','#%d/%m%Y#'));
The only Thing I could imagine at the Moment would be to Change your Column-Type from DateTime to varchar and use a BEFORE INSERT Trigger to fix "wrong" Dates.
Something like this:
DELIMITER //
CREATE TRIGGER t1 BEFORE INSERT on myTable FOR EACH ROW
BEGIN
IF (NEW.myDate regexp '#[[:digit:]]+\/[[:digit:]]+\/[[:digit:]]+#') THEN
SET NEW.myDate = STR_TO_DATE(NEW.myDate,'#%d/%m/%Y#');
END IF;
END; //
DELIMITER ;
If you are just Need to run the Import in question once, use the Trigger to generate a "proper" dateTimeColumn out of the inserts - and drop the varchar-column afterwards:
('myDate' := varchar column to be dropped afterwards;`'myRealDate' := DateTime Column to Keep afterwards)
DELIMITER //
CREATE TRIGGER t1 BEFORE INSERT on myTable FOR EACH ROW
BEGIN
IF (NEW.myDate regexp '#[[:digit:]]+\/[[:digit:]]+\/[[:digit:]]+#') THEN
SET NEW.myRealDate = STR_TO_DATE(NEW.myDate,'#%d/%m/%Y#');
else
#assume a valid date representation
SET NEW.myRealDate = NEW.myDate;
END IF;
END; //
DELIMITER ;
Unfortunately you cannot use a Trigger to work on the datetime-column itself, because mysql will already mess up the NEW.myDate-Column.

How to find out the changes happened for all objects

How I can find out the changes happened in database like modifying functions, table indexes, procedures and adding or removing columns.
Here in this query
select * from sys.objects
where type IS NOT NULL
and modify_date between '2013-07-21' and '2013-07-29'
but here I am getting created objects list and modifying list, but if I deleted any object it is not showing anything.
How can I get the all the changes happened in database between specific dates?
Try a source control solution for SQL. I've used RedGate's SQL Source Control before, and it records a history of changes like this, including who made the change, and what was changed.
http://www.red-gate.com/products/sql-development/sql-source-control/
It's a bit expensive, but it's good. I don't know if there's a way to do it (especially deletions) just with SQL itself.
Many of these incidents are recorded in the default trace.
DECLARE #path NVARCHAR(260);
SELECT
#path = REVERSE(SUBSTRING(REVERSE([path]),
CHARINDEX(CHAR(92), REVERSE([path])), 260)) + N'log.trc'
FROM sys.traces
WHERE is_default = 1;
SELECT
LoginName,
HostName,
StartTime,
ObjectName,
TextData -- may or may not be populated
FROM sys.fn_trace_gettable(#path, DEFAULT)
WHERE EventClass IN
(
164, -- object:altered
46, -- object:created
47 -- object:deleted
)
AND StartTime >= '20130721' AND StartTime < '20130730';
Why you should never use BETWEEN for date range queries.

MySQL using table columns in function to create alias to be used in sorting

It sounds more complicated than it actually is. Here is what I'm trying to do within the SELECT part:
SELECT TIMESTAMPADD(
UCASE(
SUBSTRING(offset_unit,1,CHAR_LENGTH(offset_unit)-1)
),1,'2003-01-02') as offset_date
offset_unit is a VARCHAR column in the database. It contains one of the following: "Hours","Minutes".
offset is an INT.
I am trying to convert the offset_unit to uppercase, after I have removed the last character ('s') so I can have a proper interval (MINUTE, HOUR...) so I can get a date that I can use in sorting afterwards, but MySQL keeps throwing an error. I have tested each step by adding one function at a time, and it only fails after I add TIMESTAMPADD. If I enter MINUTE manually then it works.
Any way to get this working?
Additional info: I am running this in CakePHP 1.3, in a find, within the 'fields' array, but that shouldn't be important.
this can be easily achived by using CASE WHEN clause as:
SELECT (CASE
WHEN offset_unit = 'HOURS'
THEN TIMESTAMPADD(HOUR,`offset`,'2003-01-02')
WHEN offset_unit = 'MINUTES'
THEN TIMESTAMPADD(MINUTE,`offset`,'2003-01-02')
END) AS offset_date
FROM my_table;
SEE SQLFIDDLE DEMO HERE
It doesn't work because TIMESTAMPADD does not take a string as the first argument, but a unit keyword, for example MINUTE. My guess is that you need to do this in two steps, first get the unit and then construct a query with the correct keyword.

DST to UTC append query creates a type conversion error in access

I have a table I'm using as a source for an append query that calls upon a table query, which calls upon a union query to effectively adjust the eastern prevailing time to spring forward and fall back while converting to utc. there are only three fields in the table but I keep getting "access did not import .... due to type conversion". Please Help Me out!!! Thank you in advance
below is the access sql:
{append query}
INSERT INTO somePrice ( price )
SELECT DTQuery.Price
FROM DTQuery
WHERE (((DTQuery.EPT)<>[2ndsunday]));
{DTQuery}
SELECT
TransposeQuery.Field3 AS [Zone]
, DateSerial(Left([field1],4),Left(Right([field1],4),2),Right([field1],2))+[TransposeQuery]![Hour]/24 AS EPT, Val([Field8]) AS Price
, DateValue(DateSerial(Year([EPT]),3,14))-(Weekday(DateValue(DateSerial(Year([EPT]),3,14)),1)-1)+3/24 AS 2ndSunday
, DateValue(DateSerial(Year([EPT]),11,7))-(Weekday(DateValue(DateSerial(Year([EPT]),11,7)),1)-1)+3/24 AS 1stSunday
FROM TransposeQuery
ORDER BY
TransposeQuery.Field3
, DateSerial(Left([field1],4),Left(Right([field1],4),2),Right([field1],2))+[TransposeQuery]![Hour]/24, Val([Field8]);
First some general stuff: If you want to convert between timezones, which involves adding or subtracting a number of hours you might want to use to DateAdd function.
DateAdd("h", -2, [SourceDateTime])
This simply takes two hours off the SourceDateTime field.
Also rather than using the Left(Right( combination you can use Mid(string, start, length)
Mid("1234567890", 2, 4)
Returns 2345, but if you are dealing with dates just use DatePart
DatePart("h", "17/12/2011 08:10")
Returns 8.
As for the type conversion error, it's hard to say as you haven't given us the types of the fields in the destination table.
If you run the append query without the first line this will rule out the destination table. If it still fails then it might be in the where clause, so move the fields into the results set and make sure they are the same type. If it still fails then it must be in the source query so check DTQuery opens without any problems.