是否可以编辑或修改内置的MySQL函数?

时间:2012-02-24 08:41:05

标签: mysql

是否可以使用MySQL命令行更改/修改MySQL内置函数,例如date()函数

或者我们可以看到实际功能的编写方式吗?

编辑实际原因

原因是我有一个自定义编写的MySQL函数,如下所示

CREATE  FUNCTION getUser() RETURNS char(50) CHARSET latin1
RETURN  @empNumber;

但是,它有点慢。我想看看实际的内置函数是如何编写的,然后我可以按照相同的步骤。

1 个答案:

答案 0 :(得分:1)

如果您有一种允许编写dll的编程语言,则可以创建自定义UDF。

请参阅此处,了解使用C:http://www.codeguru.com/cpp/data/mfc_database/misc/article.php/c12615

的示例

这里有一个使用Delphi的例子:http://www.sherlocksoftware.org/page.php?id=58

以下是levenshtein函数的示例源代码(Delphi):

unit udf_levenshtein;

interface

{Nicholas Sherlock, 2006.

 Example of a UDF: Levenshtein string distance.
 After copying the dll to your MySql/bin folder, create with:
 CREATE FUNCTION Levenshtein RETURNS INT SONAME 'LevenshteinUDF.dll';}

uses SysUtils, mysql_udf;

function stringdistance(const s, t: string): integer; overload;
function stringdistance(const s, t: string; maxdist: integer; out dist: integer): boolean; overload;

implementation

type
  TIntArray = array[0..maxint div 4 - 1] of integer; {Avoid errors if range check on}
  pintarray = ^TIntArray;

function Levenshtein_init(var init: UDF_INIT; var _args: UDF_ARGS; message: pChar): my_bool; cdecl;
var args: TUDF_Args;
begin
  result := 0;
  args := TUDF_Args.create(@_args);
  try
    if (not (args.Count in [2..3])) or ((args.count = 3) and (args[2].ArgType <> INT_RESULT)) then begin
      strcopy(message, 'Levenshtein() usage: Levenshtein(string1, string2 [,maxdist])');
      result := 1; //fail
      exit;
    end;

    args[0].ArgType := STRING_RESULT;
    args[1].ArgType := STRING_RESULT; //Mysql will now coerce these args to string for us

    if args.count = 3 then
      init.maybe_null := 1 else //since we could exceed maxdist
      init.maybe_null := 0;

  finally
    args.free;
  end;
end;

procedure Levenshtein_deinit(var init: UDF_INIT); cdecl;
begin
 {Do nothing. We could actually omit this function, MySql won't
  try to call it if it doesn't exist}
end;

function Levenshtein(var init: UDF_INIT; var _args: UDF_ARGS; var is_null, error: byte): int64; cdecl;
var args: TUDF_Args;
  dist: integer;
begin
  error := 0;
  is_null := 0;
  args := TUDF_Args.create(@_args);
  try
    if args.Count >= 3 then begin
      if not stringdistance(args[0].DataString, args[1].DataString, args[2].DataInteger, dist) then begin
        result := 0;
        is_null := 1;
      end else //didn't fall inside maximum distance
        result := dist;
    end else
      result := stringdistance(args[0].DataString, args[1].DataString);
  finally
    args.free;
  end;
end;

function min3(a, b, c: integer): integer;
begin
  if (a <= b) and (a <= c) then begin
    result := a;
    exit;
  end;
  if (b <= a) and (b <= c) then begin
    result := b;
    Exit;
  end;
  result := c;
end;

{Find the distance between the two strings s and t. We are only interested in
 the distance if the distance is less than or equal to maxdist. The result is
 true if the distance has been found (Distance stored in dist), it may be greater
 than maxdist. If the result is false, then the distance has not been found, but
 it is greater than maxdist}

function stringdistance(const s, t: string; maxdist: integer; out dist: integer): boolean;
const
  cost_ins = 1;
  cost_del = 1;
  cost_sub = 1;
var n, m: integer;
  p, q, r: PIntArray;
  smallest, cost, i, j: integer;
begin
  result := false; //Didn't meet max dist requirement

  m := length(s);
  n := length(t);

  if abs(m - n) > maxdist then
    exit; //dist is always at least the difference between lengths of args

  if n = 0 then begin
    dist := m;
    result := true;
    exit;
  end else
    if m = 0 then begin
      dist := n;
      result := true;
      exit;
    end;

  getmem(p, (n + 1) * SizeOf(integer)); {p is first row}
  getmem(q, (n + 1) * SizeOf(integer)); {q is second row}

  p[0] := 0;
  for i := 1 to n do
    p[i] := p[i - 1] + cost_ins; {fill first row}

  for i := 1 to m do begin
    q[0] := p[0] + cost_del; //cost del
    smallest := q[0];
    for j := 1 to n do begin
      if s[i] = t[j] then cost := 0 else cost := cost_sub;
      q[j] := min3(p[j] + cost_del,
        q[j - 1] + cost_ins,
        p[j - 1] + cost {cost subst}
        );
        if q[j]<smallest then
        smallest:=q[j];
    end;
    if smallest > maxdist then
      exit; //exceeded maxdist

    r := p; {Swap over the two rows}
    p := q;
    q := r;
  end;

  dist := p[n];
  result := true;

  FreeMem(p);
  FreeMem(q);
end;

function stringdistance(const s, t: string): integer;
const
  cost_ins = 1;
  cost_del = 1;
  cost_sub = 1;
var n, m: integer;
  p, q, r: PIntArray;
  cost, i, j: integer;
begin
  m := length(s);
  n := length(t);

  if n = 0 then begin
    result := m;
    exit;
  end else
    if m = 0 then begin
      result := n;
      exit;
    end;

  getmem(p, (n + 1) * SizeOf(integer)); {p is first row}
  getmem(q, (n + 1) * SizeOf(integer)); {q is second row}

  p[0] := 0;
  for i := 1 to n do
    p[i] := p[i - 1] + cost_ins; {fill first row}

  for i := 1 to m do begin
    q[0] := p[0] + cost_del;
    for j := 1 to n do begin
      if s[i] = t[j] then cost := 0 else cost := cost_sub;
      q[j] := min3(p[j] + cost_del, {cost del}
        q[j - 1] + cost_ins, {cost ins}
        p[j - 1] + cost {cost subst}
        );
    end;

    r := p; {Swap over the two rows}
    p := q;
    q := r;
  end;

  result := p[n];

  FreeMem(p);
  FreeMem(q);
end;

exports
  Levenshtein_init,
  Levenshtein,
  Levenshtein_deinit;

end.