数据库:参数化的日期字符串比较时也转换格式

- 教材项目 8 用参数传 "2024/1/23  23:59:59"(日期和时间之间两个空格)做 BETWEEN,
  比较时用 tsql_cmp 把形如日期的字符串转成标准格式;日期和时间之间允许多个空格

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
xuyueandClaude Opus 5.5 committed 2026-10-23 15:13:28 +08:00
1 parent 19d6872d80
commit 13c3e4c3ec
3 files changed
+14 -2

No files matched your search

+1
View File
@@ -44,6 +44,7 @@ internal static class Functions
c.CreateFunction<object?, object?>("tsql_ceiling", x => x is null ? null : Math.Ceiling(ToDouble(x)), isDeterministic: true);
c.CreateFunction<object?, object?, object?>("tsql_power", (x, y) => x is null || y is null ? null : Math.Pow(ToDouble(x), ToDouble(y)), isDeterministic: true);
c.CreateFunction<object?, object?>("tsql_sqrt", x => x is null ? null : Math.Sqrt(ToDouble(x)), isDeterministic: true);
c.CreateFunction<object?, object?>("tsql_cmp", v => v is string s && Values.LooksLikeDate(s) ? Values.NormalizeDateLiteral(s) : v, isDeterministic: true);
c.CreateFunction("tsql_newid", () => Guid.NewGuid().ToString().ToUpperInvariant());
c.CreateFunction("tsql_rand", () => Random.Shared.NextDouble());
}
+8
View File
@@ -911,6 +911,14 @@ internal sealed class Translator
_sql.Append(Values.Quote(Values.NormalizeDateLiteral(s.Value)));
return;
}
// 参数的值执行时才知道:是日期样子的字符串时同样转成标准格式(教材 BETWEEN @time_start AND @time_end 传的是字符串)
if (expression is VariableReference)
{
_sql.Append("tsql_cmp(");
Expression(expression);
_sql.Append(')');
return;
}
Expression(expression);
}
}
+5 -2
View File
@@ -17,13 +17,16 @@ internal static class Values
};
/// <summary>形如日期的字符串字面量(比较时转成标准格式,例如 BETWEEN '2024/1/16 9:05:03' AND ...)</summary>
private static readonly Regex DateLike = new(@"^\d{4}[-/.]\d{1,2}[-/.]\d{1,2}([ T]\d{1,2}:\d{1,2}(:\d{1,2}(\.\d+)?)?)?$");
private static readonly Regex DateLike = new(@"^\d{4}[-/.]\d{1,2}[-/.]\d{1,2}((\s+|T)\d{1,2}:\d{1,2}(:\d{1,2}(\.\d+)?)?)?$");
/// <summary>日期和时间之间多余的空格(教材拼出的 "2024/1/23 23:59:59")</summary>
private static readonly Regex Spaces = new(@"\s+");
public static bool LooksLikeDate(string text) => DateLike.IsMatch(text.Trim());
/// <summary>按 SQL Server 接受的写法解析日期(包括中文 Windows 上 DateTime.ToString() 的 2024/1/16 9:05:03)</summary>
public static bool TryParseDateTime(string text, out DateTime value) =>
DateTime.TryParseExact(text.Trim(), DateFormats, CultureInfo.InvariantCulture, DateTimeStyles.AllowWhiteSpaces, out value);
DateTime.TryParseExact(Spaces.Replace(text.Trim(), " "), DateFormats, CultureInfo.InvariantCulture, DateTimeStyles.AllowWhiteSpaces, out value);
public static string FormatDateTime(DateTime value) =>
value.Millisecond == 0 && value.Ticks % TimeSpan.TicksPerMillisecond == 0